mirror of
https://github.com/postgrespro/pg_probackup.git
synced 2024-11-28 09:33:54 +02:00
TESTS: false_positive added, pgpro-560 added, validate redesign
This commit is contained in:
parent
134c9390b2
commit
0f212e0455
@ -5,16 +5,16 @@ from . import init_test, option_test, show_test, \
|
|||||||
retention_test, ptrack_clean, ptrack_cluster, \
|
retention_test, ptrack_clean, ptrack_cluster, \
|
||||||
ptrack_move_to_tablespace, ptrack_recovery, ptrack_vacuum, \
|
ptrack_move_to_tablespace, ptrack_recovery, ptrack_vacuum, \
|
||||||
ptrack_vacuum_bits_frozen, ptrack_vacuum_bits_visibility, \
|
ptrack_vacuum_bits_frozen, ptrack_vacuum_bits_visibility, \
|
||||||
ptrack_vacuum_full, ptrack_vacuum_truncate, common_archive_test, \
|
ptrack_vacuum_full, ptrack_vacuum_truncate, pgpro560, pgpro589, \
|
||||||
pgpro561, pgpro688, pgpro702, pgpro589
|
false_positive, replica
|
||||||
|
|
||||||
|
|
||||||
def load_tests(loader, tests, pattern):
|
def load_tests(loader, tests, pattern):
|
||||||
suite = unittest.TestSuite()
|
suite = unittest.TestSuite()
|
||||||
suite.addTests(loader.loadTestsFromModule(pgpro561))
|
suite.addTests(loader.loadTestsFromModule(replica))
|
||||||
|
suite.addTests(loader.loadTestsFromModule(pgpro560))
|
||||||
suite.addTests(loader.loadTestsFromModule(pgpro589))
|
suite.addTests(loader.loadTestsFromModule(pgpro589))
|
||||||
suite.addTests(loader.loadTestsFromModule(pgpro688))
|
suite.addTests(loader.loadTestsFromModule(false_positive))
|
||||||
suite.addTests(loader.loadTestsFromModule(pgpro702))
|
|
||||||
suite.addTests(loader.loadTestsFromModule(init_test))
|
suite.addTests(loader.loadTestsFromModule(init_test))
|
||||||
suite.addTests(loader.loadTestsFromModule(option_test))
|
suite.addTests(loader.loadTestsFromModule(option_test))
|
||||||
suite.addTests(loader.loadTestsFromModule(show_test))
|
suite.addTests(loader.loadTestsFromModule(show_test))
|
||||||
@ -34,3 +34,6 @@ def load_tests(loader, tests, pattern):
|
|||||||
suite.addTests(loader.loadTestsFromModule(ptrack_vacuum_truncate))
|
suite.addTests(loader.loadTestsFromModule(ptrack_vacuum_truncate))
|
||||||
|
|
||||||
return suite
|
return suite
|
||||||
|
|
||||||
|
|
||||||
|
# ExpectedFailures are bugs, which should be fixed
|
||||||
|
@ -10,10 +10,12 @@ class BackupTest(ProbackupTest, unittest.TestCase):
|
|||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(BackupTest, self).__init__(*args, **kwargs)
|
super(BackupTest, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
# @classmethod
|
@classmethod
|
||||||
# def tearDownClass(cls):
|
def tearDownClass(cls):
|
||||||
# stop_all()
|
stop_all()
|
||||||
# @unittest.skip("123")
|
|
||||||
|
# @unittest.skip("skip")
|
||||||
|
# @unittest.expectedFailure
|
||||||
def test_backup_modes_archive(self):
|
def test_backup_modes_archive(self):
|
||||||
"""standart backup modes with ARCHIVE WAL method"""
|
"""standart backup modes with ARCHIVE WAL method"""
|
||||||
fname = self.id().split('.')[3]
|
fname = self.id().split('.')[3]
|
||||||
@ -26,8 +28,10 @@ class BackupTest(ProbackupTest, unittest.TestCase):
|
|||||||
self.assertEqual(self.init_pb(node), six.b(""))
|
self.assertEqual(self.init_pb(node), six.b(""))
|
||||||
|
|
||||||
# full backup mode
|
# full backup mode
|
||||||
with open(path.join(node.logs_dir, "backup_full.log"), "wb") as backup_log:
|
#with open(path.join(node.logs_dir, "backup_full.log"), "wb") as backup_log:
|
||||||
backup_log.write(self.backup_pb(node, options=["--verbose"]))
|
# backup_log.write(self.backup_pb(node, options=["--verbose"]))
|
||||||
|
|
||||||
|
self.backup_pb(node)
|
||||||
|
|
||||||
show_backup = self.show_pb(node)[0]
|
show_backup = self.show_pb(node)[0]
|
||||||
full_backup_id = show_backup['ID']
|
full_backup_id = show_backup['ID']
|
||||||
@ -46,8 +50,7 @@ class BackupTest(ProbackupTest, unittest.TestCase):
|
|||||||
self.assertEqual(excluded, True)
|
self.assertEqual(excluded, True)
|
||||||
|
|
||||||
# page backup mode
|
# page backup mode
|
||||||
with open(path.join(node.logs_dir, "backup_page.log"), "wb") as backup_log:
|
self.backup_pb(node, backup_type="page")
|
||||||
backup_log.write(self.backup_pb(node, backup_type="page", options=["--verbose"]))
|
|
||||||
|
|
||||||
# print self.show_pb(node)
|
# print self.show_pb(node)
|
||||||
show_backup = self.show_pb(node)[1]
|
show_backup = self.show_pb(node)[1]
|
||||||
@ -60,8 +63,7 @@ class BackupTest(ProbackupTest, unittest.TestCase):
|
|||||||
self.show_pb(node, id=show_backup['ID'])["parent-backup-id"])
|
self.show_pb(node, id=show_backup['ID'])["parent-backup-id"])
|
||||||
|
|
||||||
# ptrack backup mode
|
# ptrack backup mode
|
||||||
with open(path.join(node.logs_dir, "backup_ptrack.log"), "wb") as backup_log:
|
self.backup_pb(node, backup_type="ptrack")
|
||||||
backup_log.write(self.backup_pb(node, backup_type="ptrack", options=["--verbose"]))
|
|
||||||
|
|
||||||
show_backup = self.show_pb(node)[2]
|
show_backup = self.show_pb(node)[2]
|
||||||
self.assertEqual(show_backup['Status'], six.b("OK"))
|
self.assertEqual(show_backup['Status'], six.b("OK"))
|
||||||
@ -69,7 +71,6 @@ class BackupTest(ProbackupTest, unittest.TestCase):
|
|||||||
|
|
||||||
node.stop()
|
node.stop()
|
||||||
|
|
||||||
# @unittest.skip("123")
|
|
||||||
def test_smooth_checkpoint(self):
|
def test_smooth_checkpoint(self):
|
||||||
"""full backup with smooth checkpoint"""
|
"""full backup with smooth checkpoint"""
|
||||||
fname = self.id().split('.')[3]
|
fname = self.id().split('.')[3]
|
||||||
@ -81,14 +82,12 @@ class BackupTest(ProbackupTest, unittest.TestCase):
|
|||||||
node.start()
|
node.start()
|
||||||
self.assertEqual(self.init_pb(node), six.b(""))
|
self.assertEqual(self.init_pb(node), six.b(""))
|
||||||
|
|
||||||
with open(path.join(node.logs_dir, "backup.log"), "wb") as backup_log:
|
self.backup_pb(node, options=["-C"])
|
||||||
backup_log.write(self.backup_pb(node, options=["--verbose", "-C"]))
|
|
||||||
|
|
||||||
self.assertEqual(self.show_pb(node)[0]['Status'], six.b("OK"))
|
self.assertEqual(self.show_pb(node)[0]['Status'], six.b("OK"))
|
||||||
|
|
||||||
node.stop()
|
node.stop()
|
||||||
|
|
||||||
# @unittest.skip("123")
|
|
||||||
def test_page_backup_without_full(self):
|
def test_page_backup_without_full(self):
|
||||||
"""page-level backup without validated full backup"""
|
"""page-level backup without validated full backup"""
|
||||||
fname = self.id().split('.')[3]
|
fname = self.id().split('.')[3]
|
||||||
@ -101,14 +100,13 @@ class BackupTest(ProbackupTest, unittest.TestCase):
|
|||||||
self.assertEqual(self.init_pb(node), six.b(""))
|
self.assertEqual(self.init_pb(node), six.b(""))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.backup_pb(node, backup_type="page", options=["--verbose"])
|
self.backup_pb(node, backup_type="page")
|
||||||
except ProbackupException, e:
|
except ProbackupException, e:
|
||||||
pass
|
pass
|
||||||
self.assertEqual(self.show_pb(node)[0]['Status'], six.b("ERROR"))
|
self.assertEqual(self.show_pb(node)[0]['Status'], six.b("ERROR"))
|
||||||
|
|
||||||
node.stop()
|
node.stop()
|
||||||
|
|
||||||
# @unittest.skip("123")
|
|
||||||
def test_ptrack_threads(self):
|
def test_ptrack_threads(self):
|
||||||
"""ptrack multi thread backup mode"""
|
"""ptrack multi thread backup mode"""
|
||||||
fname = self.id().split('.')[3]
|
fname = self.id().split('.')[3]
|
||||||
@ -120,19 +118,17 @@ class BackupTest(ProbackupTest, unittest.TestCase):
|
|||||||
node.start()
|
node.start()
|
||||||
self.assertEqual(self.init_pb(node), six.b(""))
|
self.assertEqual(self.init_pb(node), six.b(""))
|
||||||
|
|
||||||
with open(path.join(node.logs_dir, "backup_full.log"), "wb") as backup_log:
|
self.backup_pb(node, backup_type="full", options=["-j", "4"])
|
||||||
backup_log.write(self.backup_pb(node, backup_type="full", options=["--verbose", "-j", "4"]))
|
|
||||||
|
|
||||||
self.assertEqual(self.show_pb(node)[0]['Status'], six.b("OK"))
|
self.assertEqual(self.show_pb(node)[0]['Status'], six.b("OK"))
|
||||||
|
|
||||||
with open(path.join(node.logs_dir, "backup_ptrack.log"), "wb") as backup_log:
|
with open(path.join(node.logs_dir, "backup_ptrack.log"), "wb") as backup_log:
|
||||||
backup_log.write(self.backup_pb(node, backup_type="ptrack", options=["--verbose", "-j", "4"]))
|
backup_log.write(self.backup_pb(node, backup_type="ptrack", options=["-j", "4"]))
|
||||||
|
|
||||||
self.assertEqual(self.show_pb(node)[0]['Status'], six.b("OK"))
|
self.assertEqual(self.show_pb(node)[0]['Status'], six.b("OK"))
|
||||||
|
|
||||||
node.stop()
|
node.stop()
|
||||||
|
|
||||||
# @unittest.skip("123")
|
|
||||||
def test_ptrack_threads_stream(self):
|
def test_ptrack_threads_stream(self):
|
||||||
"""ptrack multi thread backup mode and stream"""
|
"""ptrack multi thread backup mode and stream"""
|
||||||
fname = self.id().split('.')[3]
|
fname = self.id().split('.')[3]
|
||||||
@ -144,21 +140,11 @@ class BackupTest(ProbackupTest, unittest.TestCase):
|
|||||||
node.start()
|
node.start()
|
||||||
self.assertEqual(self.init_pb(node), six.b(""))
|
self.assertEqual(self.init_pb(node), six.b(""))
|
||||||
|
|
||||||
with open(path.join(node.logs_dir, "backup_full.log"), "wb") as backup_log:
|
self.backup_pb(node, backup_type="full", options=["-j", "4", "--stream"])
|
||||||
backup_log.write(self.backup_pb(
|
|
||||||
node,
|
|
||||||
backup_type="full",
|
|
||||||
options=["--verbose", "-j", "4", "--stream"]
|
|
||||||
))
|
|
||||||
|
|
||||||
self.assertEqual(self.show_pb(node)[0]['Status'], six.b("OK"))
|
self.assertEqual(self.show_pb(node)[0]['Status'], six.b("OK"))
|
||||||
|
|
||||||
with open(path.join(node.logs_dir, "backup_ptrack.log"), "wb") as backup_log:
|
self.backup_pb(node, backup_type="ptrack", options=["-j", "4", "--stream"])
|
||||||
backup_log.write(self.backup_pb(
|
|
||||||
node,
|
|
||||||
backup_type="ptrack",
|
|
||||||
options=["--verbose", "-j", "4", "--stream"]
|
|
||||||
))
|
|
||||||
|
|
||||||
self.assertEqual(self.show_pb(node)[1]['Status'], six.b("OK"))
|
self.assertEqual(self.show_pb(node)[1]['Status'], six.b("OK"))
|
||||||
node.stop()
|
node.stop()
|
||||||
|
@ -11,10 +11,12 @@ class DeleteTest(ProbackupTest, unittest.TestCase):
|
|||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(DeleteTest, self).__init__(*args, **kwargs)
|
super(DeleteTest, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
# @classmethod
|
@classmethod
|
||||||
# def tearDownClass(cls):
|
def tearDownClass(cls):
|
||||||
# stop_all()
|
stop_all()
|
||||||
# @unittest.skip("123")
|
|
||||||
|
# @unittest.skip("skip")
|
||||||
|
# @unittest.expectedFailure
|
||||||
def test_delete_full_backups(self):
|
def test_delete_full_backups(self):
|
||||||
"""delete full backups"""
|
"""delete full backups"""
|
||||||
fname = self.id().split('.')[3]
|
fname = self.id().split('.')[3]
|
||||||
@ -28,22 +30,19 @@ class DeleteTest(ProbackupTest, unittest.TestCase):
|
|||||||
node.pgbench_init()
|
node.pgbench_init()
|
||||||
|
|
||||||
# full backup mode
|
# full backup mode
|
||||||
with open(path.join(node.logs_dir, "backup_1.log"), "wb") as backup_log:
|
self.backup_pb(node)
|
||||||
backup_log.write(self.backup_pb(node, options=["--verbose"]))
|
|
||||||
|
|
||||||
pgbench = node.pgbench(stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
pgbench = node.pgbench(stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
pgbench.wait()
|
pgbench.wait()
|
||||||
pgbench.stdout.close()
|
pgbench.stdout.close()
|
||||||
|
|
||||||
with open(path.join(node.logs_dir, "backup_2.log"), "wb") as backup_log:
|
self.backup_pb(node)
|
||||||
backup_log.write(self.backup_pb(node, options=["--verbose"]))
|
|
||||||
|
|
||||||
pgbench = node.pgbench(stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
pgbench = node.pgbench(stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
pgbench.wait()
|
pgbench.wait()
|
||||||
pgbench.stdout.close()
|
pgbench.stdout.close()
|
||||||
|
|
||||||
with open(path.join(node.logs_dir, "backup_3.log"), "wb") as backup_log:
|
self.backup_pb(node)
|
||||||
backup_log.write(self.backup_pb(node, options=["--verbose"]))
|
|
||||||
|
|
||||||
show_backups = self.show_pb(node)
|
show_backups = self.show_pb(node)
|
||||||
id_1 = show_backups[0]['ID']
|
id_1 = show_backups[0]['ID']
|
||||||
@ -55,7 +54,6 @@ class DeleteTest(ProbackupTest, unittest.TestCase):
|
|||||||
|
|
||||||
node.stop()
|
node.stop()
|
||||||
|
|
||||||
# @unittest.skip("123")
|
|
||||||
def test_delete_increment(self):
|
def test_delete_increment(self):
|
||||||
"""delete increment and all after him"""
|
"""delete increment and all after him"""
|
||||||
fname = self.id().split('.')[3]
|
fname = self.id().split('.')[3]
|
||||||
@ -68,16 +66,13 @@ class DeleteTest(ProbackupTest, unittest.TestCase):
|
|||||||
self.assertEqual(self.init_pb(node), six.b(""))
|
self.assertEqual(self.init_pb(node), six.b(""))
|
||||||
|
|
||||||
# full backup mode
|
# full backup mode
|
||||||
with open(path.join(node.logs_dir, "backup_1.log"), "wb") as backup_log:
|
self.backup_pb(node)
|
||||||
backup_log.write(self.backup_pb(node, options=["--verbose"]))
|
|
||||||
|
|
||||||
# page backup mode
|
# page backup mode
|
||||||
with open(path.join(node.logs_dir, "backup_2.log"), "wb") as backup_log:
|
self.backup_pb(node, backup_type="page")
|
||||||
backup_log.write(self.backup_pb(node, backup_type="page", options=["--verbose"]))
|
|
||||||
|
|
||||||
# page backup mode
|
# page backup mode
|
||||||
with open(path.join(node.logs_dir, "backup_3.log"), "wb") as backup_log:
|
self.backup_pb(node, backup_type="page")
|
||||||
backup_log.write(self.backup_pb(node, backup_type="page", options=["--verbose"]))
|
|
||||||
|
|
||||||
# full backup mode
|
# full backup mode
|
||||||
self.backup_pb(node)
|
self.backup_pb(node)
|
||||||
|
@ -9,7 +9,13 @@ pg_probackup - utility to manage backup/recovery of PostgreSQL database.
|
|||||||
|
|
||||||
pg_probackup set-config -B backup-dir
|
pg_probackup set-config -B backup-dir
|
||||||
[-d dbname] [-h host] [-p port] [-U username]
|
[-d dbname] [-h host] [-p port] [-U username]
|
||||||
[--retention-redundancy=retention-redundancy]]
|
[--log-level=log-level]
|
||||||
|
[--log-filename=log-filename]
|
||||||
|
[--error-log-filename=error-log-filename]
|
||||||
|
[--log-directory=log-directory]
|
||||||
|
[--log-rotation-size=log-rotation-size]
|
||||||
|
[--log-rotation-age=log-rotation-age]
|
||||||
|
[--retention-redundancy=retention-redundancy]
|
||||||
[--retention-window=retention-window]
|
[--retention-window=retention-window]
|
||||||
|
|
||||||
pg_probackup show-config -B backup-dir
|
pg_probackup show-config -B backup-dir
|
||||||
@ -17,16 +23,16 @@ pg_probackup - utility to manage backup/recovery of PostgreSQL database.
|
|||||||
pg_probackup backup -B backup-path -b backup-mode
|
pg_probackup backup -B backup-path -b backup-mode
|
||||||
[-D pgdata-dir] [-C] [--stream [-S slot-name]] [--backup-pg-log]
|
[-D pgdata-dir] [-C] [--stream [-S slot-name]] [--backup-pg-log]
|
||||||
[-j num-threads] [--archive-timeout=archive-timeout]
|
[-j num-threads] [--archive-timeout=archive-timeout]
|
||||||
[--progress] [-q] [-v] [--delete-expired]
|
[--progress] [--delete-expired]
|
||||||
[-d dbname] [-h host] [-p port] [-U username]
|
[-d dbname] [-h host] [-p port] [-U username]
|
||||||
|
|
||||||
pg_probackup restore -B backup-dir
|
pg_probackup restore -B backup-dir
|
||||||
[-D pgdata-dir] [-i backup-id] [--progress] [-q] [-v]
|
[-D pgdata-dir] [-i backup-id] [--progress]
|
||||||
[--time=time|--xid=xid [--inclusive=boolean]]
|
[--time=time|--xid=xid [--inclusive=boolean]]
|
||||||
[--timeline=timeline] [-T OLDDIR=NEWDIR]
|
[--timeline=timeline] [-T OLDDIR=NEWDIR]
|
||||||
|
|
||||||
pg_probackup validate -B backup-dir
|
pg_probackup validate -B backup-dir
|
||||||
[-D pgdata-dir] [-i backup-id] [--progress] [-q] [-v]
|
[-D pgdata-dir] [-i backup-id] [--progress]
|
||||||
[--time=time|--xid=xid [--inclusive=boolean]]
|
[--time=time|--xid=xid [--inclusive=boolean]]
|
||||||
[--timeline=timeline]
|
[--timeline=timeline]
|
||||||
|
|
||||||
|
154
tests/false_positive.py
Normal file
154
tests/false_positive.py
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
import unittest
|
||||||
|
import os
|
||||||
|
import six
|
||||||
|
from .ptrack_helpers import ProbackupTest, ProbackupException
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
from testgres import stop_all
|
||||||
|
import subprocess
|
||||||
|
from sys import exit
|
||||||
|
|
||||||
|
|
||||||
|
class FalsePositive(ProbackupTest, unittest.TestCase):
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(FalsePositive, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
stop_all()
|
||||||
|
|
||||||
|
# @unittest.skip("skip")
|
||||||
|
# @unittest.expectedFailure
|
||||||
|
def test_pgpro561(self):
|
||||||
|
"""
|
||||||
|
make node with archiving, make stream backup, restore it to node1,
|
||||||
|
check that archiving is not successful on node1
|
||||||
|
"""
|
||||||
|
fname = self.id().split('.')[3]
|
||||||
|
master = self.make_simple_node(base_dir="tmp_dirs/false_positive/{0}/master".format(fname),
|
||||||
|
set_archiving=True,
|
||||||
|
set_replication=True,
|
||||||
|
initdb_params=['--data-checksums'],
|
||||||
|
pg_options={'wal_level': 'replica', 'max_wal_senders': '2'}
|
||||||
|
)
|
||||||
|
master.start()
|
||||||
|
|
||||||
|
self.assertEqual(self.init_pb(master), six.b(""))
|
||||||
|
id = self.backup_pb(master, backup_type='full', options=["--stream"])
|
||||||
|
|
||||||
|
node1 = self.make_simple_node(base_dir="tmp_dirs/false_positive/{0}/node1".format(fname))
|
||||||
|
node1.cleanup()
|
||||||
|
|
||||||
|
master.psql(
|
||||||
|
"postgres",
|
||||||
|
"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,256) i")
|
||||||
|
|
||||||
|
self.backup_pb(master, backup_type='page', options=["--stream"])
|
||||||
|
self.restore_pb(backup_dir=self.backup_dir(master), data_dir=node1.data_dir)
|
||||||
|
node1.append_conf('postgresql.auto.conf', 'port = {0}'.format(node1.port))
|
||||||
|
node1.start({"-t": "600"})
|
||||||
|
|
||||||
|
timeline_master = master.get_control_data()["Latest checkpoint's TimeLineID"]
|
||||||
|
timeline_node1 = node1.get_control_data()["Latest checkpoint's TimeLineID"]
|
||||||
|
self.assertEqual(timeline_master, timeline_node1, "Timelines on Master and Node1 should be equal. This is unexpected")
|
||||||
|
|
||||||
|
archive_command_master = master.safe_psql("postgres", "show archive_command")
|
||||||
|
archive_command_node1 = node1.safe_psql("postgres", "show archive_command")
|
||||||
|
self.assertEqual(archive_command_master, archive_command_node1, "Archive command on Master and Node should be equal. This is unexpected")
|
||||||
|
|
||||||
|
res = node1.safe_psql("postgres", "select last_failed_wal from pg_stat_get_archiver() where last_failed_wal is not NULL")
|
||||||
|
# self.assertEqual(res, six.b(""), 'Restored Node1 failed to archive segment {0} due to having the same archive command as Master'.format(res.rstrip()))
|
||||||
|
if res == six.b(""):
|
||||||
|
self.assertEqual(1, 0, 'Error is expected due to Master and Node1 having the common archive and archive_command')
|
||||||
|
|
||||||
|
master.stop()
|
||||||
|
node1.stop()
|
||||||
|
|
||||||
|
def pgpro688(self):
|
||||||
|
"""
|
||||||
|
make node with archiving, make backup,
|
||||||
|
get Recovery Time, validate to Recovery Time
|
||||||
|
Waiting PGPRO-688
|
||||||
|
"""
|
||||||
|
fname = self.id().split('.')[3]
|
||||||
|
node = self.make_simple_node(base_dir="tmp_dirs/false_positive/{0}".format(fname),
|
||||||
|
set_archiving=True,
|
||||||
|
initdb_params=['--data-checksums'],
|
||||||
|
pg_options={'wal_level': 'replica', 'max_wal_senders': '2'}
|
||||||
|
)
|
||||||
|
node.start()
|
||||||
|
|
||||||
|
self.assertEqual(self.init_pb(node), six.b(""))
|
||||||
|
id = self.backup_pb(node, backup_type='full')
|
||||||
|
recovery_time = self.show_pb(node, id=id)['recovery-time']
|
||||||
|
|
||||||
|
# Uncommenting this section will make this test True Positive
|
||||||
|
#node.psql("postgres", "select pg_create_restore_point('123')")
|
||||||
|
#node.psql("postgres", "select txid_current()")
|
||||||
|
#node.psql("postgres", "select pg_switch_xlog()")
|
||||||
|
####
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.validate_pb(node, options=["--time='{0}'".format(recovery_time)])
|
||||||
|
self.assertEqual(1, 0, 'Error is expected because We should not be able safely validate "Recovery Time" without wal record with timestamp')
|
||||||
|
except ProbackupException, e:
|
||||||
|
self.assertTrue('WARNING: recovery can be done up to time {0}'.format(recovery_time) in e.message)
|
||||||
|
|
||||||
|
node.stop()
|
||||||
|
|
||||||
|
def pgpro702_688(self):
|
||||||
|
"""
|
||||||
|
make node without archiving, make stream backup,
|
||||||
|
get Recovery Time, validate to Recovery Time
|
||||||
|
"""
|
||||||
|
fname = self.id().split('.')[3]
|
||||||
|
node = self.make_simple_node(base_dir="tmp_dirs/false_positive/{0}".format(fname),
|
||||||
|
set_replication=True,
|
||||||
|
initdb_params=['--data-checksums'],
|
||||||
|
pg_options={'wal_level': 'replica', 'max_wal_senders': '2'}
|
||||||
|
)
|
||||||
|
node.start()
|
||||||
|
|
||||||
|
self.assertEqual(self.init_pb(node), six.b(""))
|
||||||
|
id = self.backup_pb(node, backup_type='full', options=["--stream"])
|
||||||
|
recovery_time = self.show_pb(node, id=id)['recovery-time']
|
||||||
|
|
||||||
|
self.assertIn(six.b("INFO: backup validation completed successfully on"),
|
||||||
|
self.validate_pb(node, options=["--time='{0}'".format(recovery_time)]))
|
||||||
|
|
||||||
|
def test_validate_wal_lost_segment(self):
|
||||||
|
"""Loose segment located between backups. ExpectedFailure. This is BUG """
|
||||||
|
fname = self.id().split('.')[3]
|
||||||
|
node = self.make_simple_node(base_dir="tmp_dirs/false_positive/{0}".format(fname),
|
||||||
|
set_archiving=True,
|
||||||
|
initdb_params=['--data-checksums'],
|
||||||
|
pg_options={'wal_level': 'replica'}
|
||||||
|
)
|
||||||
|
|
||||||
|
node.start()
|
||||||
|
self.assertEqual(self.init_pb(node), six.b(""))
|
||||||
|
self.backup_pb(node, backup_type='full')
|
||||||
|
|
||||||
|
# make some wals
|
||||||
|
node.pgbench_init(scale=2)
|
||||||
|
pgbench = node.pgbench(
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.STDOUT,
|
||||||
|
options=["-c", "4", "-T", "10"]
|
||||||
|
)
|
||||||
|
pgbench.wait()
|
||||||
|
pgbench.stdout.close()
|
||||||
|
|
||||||
|
# delete last wal segment
|
||||||
|
wals_dir = os.path.join(self.backup_dir(node), "wal")
|
||||||
|
wals = [f for f in os.listdir(wals_dir) if os.path.isfile(os.path.join(wals_dir, f)) and not f.endswith('.backup')]
|
||||||
|
wals = map(int, wals)
|
||||||
|
os.remove(os.path.join(self.backup_dir(node), "wal", '0000000' + str(max(wals))))
|
||||||
|
|
||||||
|
|
||||||
|
##### Hole Smokes, Batman! We just lost a wal segment and know nothing about it
|
||||||
|
##### We need archive-push ASAP
|
||||||
|
self.backup_pb(node, backup_type='full')
|
||||||
|
self.assertTrue('validation completed successfully' in self.validate_pb(node))
|
||||||
|
########
|
||||||
|
node.stop()
|
@ -12,6 +12,8 @@ class InitTest(ProbackupTest, unittest.TestCase):
|
|||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(InitTest, self).__init__(*args, **kwargs)
|
super(InitTest, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
# @unittest.skip("skip")
|
||||||
|
# @unittest.expectedFailure
|
||||||
def test_success_1(self):
|
def test_success_1(self):
|
||||||
"""Success normal init"""
|
"""Success normal init"""
|
||||||
fname = self.id().split(".")[3]
|
fname = self.id().split(".")[3]
|
||||||
|
@ -14,6 +14,8 @@ class OptionTest(ProbackupTest, unittest.TestCase):
|
|||||||
def tearDownClass(cls):
|
def tearDownClass(cls):
|
||||||
stop_all()
|
stop_all()
|
||||||
|
|
||||||
|
# @unittest.skip("skip")
|
||||||
|
# @unittest.expectedFailure
|
||||||
def test_help_1(self):
|
def test_help_1(self):
|
||||||
"""help options"""
|
"""help options"""
|
||||||
fname = self.id().split(".")[3]
|
fname = self.id().split(".")[3]
|
||||||
|
78
tests/pgpro560.py
Normal file
78
tests/pgpro560.py
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
import unittest
|
||||||
|
import os
|
||||||
|
import six
|
||||||
|
from .ptrack_helpers import ProbackupTest, ProbackupException, idx_ptrack
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
from testgres import stop_all
|
||||||
|
import subprocess
|
||||||
|
from sys import exit
|
||||||
|
|
||||||
|
|
||||||
|
class CheckSystemID(ProbackupTest, unittest.TestCase):
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(CheckSystemID, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
stop_all()
|
||||||
|
|
||||||
|
# @unittest.skip("skip")
|
||||||
|
# @unittest.expectedFailure
|
||||||
|
def test_pgpro560_control_file_loss(self):
|
||||||
|
"""
|
||||||
|
https://jira.postgrespro.ru/browse/PGPRO-560
|
||||||
|
make node with stream support, delete control file
|
||||||
|
make backup
|
||||||
|
check that backup failed
|
||||||
|
"""
|
||||||
|
fname = self.id().split('.')[3]
|
||||||
|
node = self.make_simple_node(base_dir="tmp_dirs/pgpro560/{0}/node".format(fname),
|
||||||
|
set_replication=True,
|
||||||
|
initdb_params=['--data-checksums'],
|
||||||
|
pg_options={'wal_level': 'replica'}
|
||||||
|
)
|
||||||
|
node.start()
|
||||||
|
|
||||||
|
self.assertEqual(self.init_pb(node), six.b(""))
|
||||||
|
file = os.path.join(node.base_dir,'data', 'global', 'pg_control')
|
||||||
|
os.remove(file)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.backup_pb(node, backup_type='full', options=['--stream'])
|
||||||
|
assertEqual(1, 0, 'Error is expected because of control file loss')
|
||||||
|
except ProbackupException, e:
|
||||||
|
self.assertTrue(
|
||||||
|
'ERROR: could not open file' and 'pg_control' in e.message,
|
||||||
|
'Expected error is about control file loss')
|
||||||
|
|
||||||
|
def test_pgpro560_systemid_mismatch(self):
|
||||||
|
"""
|
||||||
|
https://jira.postgrespro.ru/browse/PGPRO-560
|
||||||
|
make node1 and node2
|
||||||
|
feed to backup PGDATA from node1 and PGPORT from node2
|
||||||
|
check that backup failed
|
||||||
|
"""
|
||||||
|
fname = self.id().split('.')[3]
|
||||||
|
node1 = self.make_simple_node(base_dir="tmp_dirs/pgpro560/{0}/node1".format(fname),
|
||||||
|
set_replication=True,
|
||||||
|
initdb_params=['--data-checksums'],
|
||||||
|
pg_options={'wal_level': 'replica'}
|
||||||
|
)
|
||||||
|
node1.start()
|
||||||
|
node2 = self.make_simple_node(base_dir="tmp_dirs/pgpro560/{0}/node2".format(fname),
|
||||||
|
set_replication=True,
|
||||||
|
initdb_params=['--data-checksums'],
|
||||||
|
pg_options={'wal_level': 'replica'}
|
||||||
|
)
|
||||||
|
node2.start()
|
||||||
|
self.assertEqual(self.init_pb(node1), six.b(""))
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.backup_pb(node1, data_dir=node2.data_dir, backup_type='full', options=['--stream'])
|
||||||
|
assertEqual(1, 0, 'Error is expected because of SYSTEM ID mismatch')
|
||||||
|
except ProbackupException, e:
|
||||||
|
self.assertTrue(
|
||||||
|
'ERROR: Backup data directory was initialized for system id' and
|
||||||
|
'but target backup directory system id is' in e.message,
|
||||||
|
'Expected error is about SYSTEM ID mismatch')
|
@ -1,62 +0,0 @@
|
|||||||
import unittest
|
|
||||||
import os
|
|
||||||
import six
|
|
||||||
from .ptrack_helpers import ProbackupTest, ProbackupException, idx_ptrack
|
|
||||||
from datetime import datetime, timedelta
|
|
||||||
from testgres import stop_all
|
|
||||||
import subprocess
|
|
||||||
from sys import exit
|
|
||||||
|
|
||||||
|
|
||||||
class CommonArchiveDir(ProbackupTest, unittest.TestCase):
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super(CommonArchiveDir, self).__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
# @classmethod
|
|
||||||
# def tearDownClass(cls):
|
|
||||||
# stop_all()
|
|
||||||
|
|
||||||
def test_pgpro561(self):
|
|
||||||
"""
|
|
||||||
EXPECTED TO FAIL
|
|
||||||
make node with archiving, make stream backup, restore it to node1,
|
|
||||||
check that archiving is not successful on node1
|
|
||||||
"""
|
|
||||||
fname = self.id().split('.')[3]
|
|
||||||
master = self.make_simple_node(base_dir="tmp_dirs/pgpro561/{0}/master".format(fname),
|
|
||||||
set_archiving=True,
|
|
||||||
set_replication=True,
|
|
||||||
initdb_params=['--data-checksums'],
|
|
||||||
pg_options={'wal_level': 'replica', 'max_wal_senders': '2'}
|
|
||||||
)
|
|
||||||
master.start()
|
|
||||||
|
|
||||||
self.assertEqual(self.init_pb(master), six.b(""))
|
|
||||||
id = self.backup_pb(master, backup_type='full', options=["--stream"])
|
|
||||||
|
|
||||||
node1 = self.make_simple_node(base_dir="tmp_dirs/pgpro561/{0}/node1".format(fname))
|
|
||||||
node1.cleanup()
|
|
||||||
|
|
||||||
master.psql(
|
|
||||||
"postgres",
|
|
||||||
"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,256) i")
|
|
||||||
|
|
||||||
self.backup_pb(master, backup_type='page', options=["--stream"])
|
|
||||||
self.restore_pb(backup_dir=self.backup_dir(master), data_dir=node1.data_dir)
|
|
||||||
node1.append_conf('postgresql.auto.conf', 'port = {0}'.format(node1.port))
|
|
||||||
node1.start({"-t": "600"})
|
|
||||||
|
|
||||||
timeline_master = master.get_control_data()["Latest checkpoint's TimeLineID"]
|
|
||||||
timeline_node1 = node1.get_control_data()["Latest checkpoint's TimeLineID"]
|
|
||||||
self.assertEqual(timeline_master, timeline_node1, "Timelines on Master and Node1 should be equal. This is unexpected")
|
|
||||||
|
|
||||||
archive_command_master = master.safe_psql("postgres", "show archive_command")
|
|
||||||
archive_command_node1 = node1.safe_psql("postgres", "show archive_command")
|
|
||||||
self.assertEqual(archive_command_master, archive_command_node1, "Archive command on Master and Node should be equal. This is unexpected")
|
|
||||||
|
|
||||||
res = node1.safe_psql("postgres", "select last_failed_wal from pg_stat_get_archiver() where last_failed_wal is not NULL")
|
|
||||||
self.assertEqual(res, six.b(""), 'Restored Node1 failed to archive segment {0} due to having the same archive command as Master'.format(res.rstrip()))
|
|
||||||
|
|
||||||
master.stop()
|
|
||||||
node1.stop()
|
|
@ -8,21 +8,22 @@ import subprocess
|
|||||||
from sys import exit
|
from sys import exit
|
||||||
|
|
||||||
|
|
||||||
class LsnCheck(ProbackupTest, unittest.TestCase):
|
class ArchiveCheck(ProbackupTest, unittest.TestCase):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(LsnCheck, self).__init__(*args, **kwargs)
|
super(ArchiveCheck, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
# @classmethod
|
@classmethod
|
||||||
# def tearDownClass(cls):
|
def tearDownClass(cls):
|
||||||
# stop_all()
|
stop_all()
|
||||||
# @unittest.expectedFailure
|
|
||||||
def test_pgpro589(self):
|
# @unittest.skip("skip")
|
||||||
|
# @unittest.expectedFailure
|
||||||
|
def test_archive_mode(self):
|
||||||
"""
|
"""
|
||||||
https://jira.postgrespro.ru/browse/PGPRO-589
|
https://jira.postgrespro.ru/browse/PGPRO-589
|
||||||
make node without archive support, make backup which should fail
|
make node without archive support, make backup which should fail
|
||||||
check that no files where copied to backup catalogue
|
check ERROR text
|
||||||
EXPECTED TO FAIL
|
|
||||||
"""
|
"""
|
||||||
fname = self.id().split('.')[3]
|
fname = self.id().split('.')[3]
|
||||||
node = self.make_simple_node(base_dir="tmp_dirs/pgpro589/{0}/node".format(fname),
|
node = self.make_simple_node(base_dir="tmp_dirs/pgpro589/{0}/node".format(fname),
|
||||||
@ -43,18 +44,54 @@ class LsnCheck(ProbackupTest, unittest.TestCase):
|
|||||||
path = node.safe_psql("postgres", "select pg_relation_filepath('pgbench_accounts')").rstrip()
|
path = node.safe_psql("postgres", "select pg_relation_filepath('pgbench_accounts')").rstrip()
|
||||||
|
|
||||||
self.assertEqual(self.init_pb(node), six.b(""))
|
self.assertEqual(self.init_pb(node), six.b(""))
|
||||||
proc = self.backup_pb(
|
|
||||||
node, backup_type='full', options=['--archive-timeout=1'], async=True)
|
|
||||||
|
|
||||||
content = proc.stderr.read()
|
try:
|
||||||
self.assertEqual(True, 'wait for LSN' in repr(content),
|
self.backup_pb(node, backup_type='full', options=['--archive-timeout=10'])
|
||||||
'No Wait for LSN')
|
assertEqual(1, 0, 'Error is expected because of disabled archive_mode')
|
||||||
self.assertEqual(True, 'could not be archived' in repr(content),
|
except ProbackupException, e:
|
||||||
'No Fail Archiving Message')
|
self.assertEqual(e.message, 'ERROR: Archiving must be enabled for archive backup\n')
|
||||||
|
|
||||||
|
def test_pgpro589(self):
|
||||||
|
"""
|
||||||
|
https://jira.postgrespro.ru/browse/PGPRO-589
|
||||||
|
make node without archive support, make backup which should fail
|
||||||
|
check that backup status equal to ERROR
|
||||||
|
check that no files where copied to backup catalogue
|
||||||
|
"""
|
||||||
|
fname = self.id().split('.')[3]
|
||||||
|
node = self.make_simple_node(base_dir="tmp_dirs/pgpro589/{0}/node".format(fname),
|
||||||
|
initdb_params=['--data-checksums'],
|
||||||
|
pg_options={'wal_level': 'replica'}
|
||||||
|
)
|
||||||
|
node.append_conf("postgresql.auto.conf", "archive_mode = on")
|
||||||
|
node.append_conf("postgresql.auto.conf", "wal_level = archive")
|
||||||
|
node.append_conf("postgresql.auto.conf", "archive_command = 'exit 0'")
|
||||||
|
node.start()
|
||||||
|
|
||||||
|
node.pgbench_init(scale=5)
|
||||||
|
pgbench = node.pgbench(
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.STDOUT,
|
||||||
|
options=["-c", "4", "-T", "10"]
|
||||||
|
)
|
||||||
|
pgbench.wait()
|
||||||
|
pgbench.stdout.close()
|
||||||
|
|
||||||
|
path = node.safe_psql("postgres", "select pg_relation_filepath('pgbench_accounts')").rstrip()
|
||||||
|
self.assertEqual(self.init_pb(node), six.b(""))
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.backup_pb(
|
||||||
|
node, backup_type='full', options=['--archive-timeout=10'])
|
||||||
|
assertEqual(1, 0, 'Error is expected because of missing archive wal segment with start_backup() LSN')
|
||||||
|
except ProbackupException, e:
|
||||||
|
self.assertTrue('INFO: wait for LSN' in e.message, "Expecting 'INFO: wait for LSN'")
|
||||||
|
self.assertTrue('ERROR: switched WAL segment' and 'could not be archived' in e.message,
|
||||||
|
"Expecting 'ERROR: switched WAL segment could not be archived'")
|
||||||
|
|
||||||
id = self.show_pb(node)[0]['ID']
|
id = self.show_pb(node)[0]['ID']
|
||||||
self.assertEqual('ERROR', self.show_pb(node, id=id)['status'], 'Backup should have ERROR status')
|
self.assertEqual('ERROR', self.show_pb(node, id=id)['status'], 'Backup should have ERROR status')
|
||||||
#print self.backup_dir(node)
|
#print self.backup_dir(node)
|
||||||
file = os.path.join(self.backup_dir(node), 'backups', id, 'database', path)
|
file = os.path.join(self.backup_dir(node), 'backups', id, 'database', path)
|
||||||
self.assertEqual(False, os.path.isfile(file),
|
self.assertFalse(os.path.isfile(file),
|
||||||
'\n Start LSN was not found in archive but datafiles where copied to backup catalogue.\n For example: {0}\n It is not optimal'.format(file))
|
'\n Start LSN was not found in archive but datafiles where copied to backup catalogue.\n For example: {0}\n It is not optimal'.format(file))
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
import unittest
|
|
||||||
import os
|
|
||||||
import six
|
|
||||||
from .ptrack_helpers import ProbackupTest, ProbackupException
|
|
||||||
from datetime import datetime, timedelta
|
|
||||||
from testgres import stop_all
|
|
||||||
import subprocess
|
|
||||||
from sys import exit
|
|
||||||
|
|
||||||
|
|
||||||
class ValidateTime(ProbackupTest, unittest.TestCase):
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super(ValidateTime, self).__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
# @classmethod
|
|
||||||
# def tearDownClass(cls):
|
|
||||||
# stop_all()
|
|
||||||
|
|
||||||
def test_validate_recovery_time(self):
|
|
||||||
"""
|
|
||||||
make node with archiving, make backup,
|
|
||||||
get Recovery Time, validate to Recovery Time
|
|
||||||
EXPECT VALIDATE TO FAIL
|
|
||||||
Waiting PGPRO-688
|
|
||||||
"""
|
|
||||||
fname = self.id().split('.')[3]
|
|
||||||
node = self.make_simple_node(base_dir="tmp_dirs/pgpro668/{0}".format(fname),
|
|
||||||
set_archiving=True,
|
|
||||||
initdb_params=['--data-checksums'],
|
|
||||||
pg_options={'wal_level': 'replica', 'max_wal_senders': '2'}
|
|
||||||
)
|
|
||||||
node.start()
|
|
||||||
|
|
||||||
self.assertEqual(self.init_pb(node), six.b(""))
|
|
||||||
id = self.backup_pb(node, backup_type='full')
|
|
||||||
recovery_time = self.show_pb(node, id=id)['recovery-time']
|
|
||||||
|
|
||||||
# Optional
|
|
||||||
#node.psql("postgres", "select pg_create_restore_point('123')")
|
|
||||||
#node.psql("postgres", "select txid_current()")
|
|
||||||
#node.psql("postgres", "select pg_switch_xlog()")
|
|
||||||
self.assertIn(six.b("INFO: backup validation completed successfully on"),
|
|
||||||
self.validate_pb(node, options=["--time='{0}'".format(recovery_time)]))
|
|
||||||
####
|
|
@ -1,39 +0,0 @@
|
|||||||
import unittest
|
|
||||||
import os
|
|
||||||
import six
|
|
||||||
from .ptrack_helpers import ProbackupTest, ProbackupException
|
|
||||||
from datetime import datetime, timedelta
|
|
||||||
from testgres import stop_all
|
|
||||||
import subprocess
|
|
||||||
from sys import exit
|
|
||||||
|
|
||||||
|
|
||||||
class ValidateTime(ProbackupTest, unittest.TestCase):
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super(ValidateTime, self).__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
# @classmethod
|
|
||||||
# def tearDownClass(cls):
|
|
||||||
# stop_all()
|
|
||||||
|
|
||||||
def test_validate_recovery_time(self):
|
|
||||||
"""
|
|
||||||
make node without archiving, make stream backup,
|
|
||||||
get Recovery Time, validate to Recovery Time
|
|
||||||
EXPECT VALIDATE TO FAIL
|
|
||||||
"""
|
|
||||||
fname = self.id().split('.')[3]
|
|
||||||
node = self.make_simple_node(base_dir="tmp_dirs/pgpro702/{0}".format(fname),
|
|
||||||
set_replication=True,
|
|
||||||
initdb_params=['--data-checksums'],
|
|
||||||
pg_options={'wal_level': 'replica', 'max_wal_senders': '2'}
|
|
||||||
)
|
|
||||||
node.start()
|
|
||||||
|
|
||||||
self.assertEqual(self.init_pb(node), six.b(""))
|
|
||||||
id = self.backup_pb(node, backup_type='full', options=["--stream"])
|
|
||||||
recovery_time = self.show_pb(node, id=id)['recovery-time']
|
|
||||||
|
|
||||||
self.assertIn(six.b("INFO: backup validation completed successfully on"),
|
|
||||||
self.validate_pb(node, options=["--time='{0}'".format(recovery_time)]))
|
|
@ -9,10 +9,10 @@ class SimpleTest(ProbackupTest, unittest.TestCase):
|
|||||||
super(SimpleTest, self).__init__(*args, **kwargs)
|
super(SimpleTest, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
def teardown(self):
|
def teardown(self):
|
||||||
# clean_all()
|
|
||||||
stop_all()
|
stop_all()
|
||||||
|
|
||||||
# @unittest.skip("123")
|
# @unittest.skip("skip")
|
||||||
|
# @unittest.expectedFailure
|
||||||
def test_ptrack_clean(self):
|
def test_ptrack_clean(self):
|
||||||
fname = self.id().split('.')[3]
|
fname = self.id().split('.')[3]
|
||||||
node = self.make_simple_node(base_dir='tmp_dirs/ptrack/{0}'.format(fname),
|
node = self.make_simple_node(base_dir='tmp_dirs/ptrack/{0}'.format(fname),
|
||||||
|
@ -12,7 +12,8 @@ class SimpleTest(ProbackupTest, unittest.TestCase):
|
|||||||
# clean_all()
|
# clean_all()
|
||||||
stop_all()
|
stop_all()
|
||||||
|
|
||||||
# @unittest.skip("123")
|
# @unittest.skip("skip")
|
||||||
|
# @unittest.expectedFailure
|
||||||
def test_ptrack_cluster_btree(self):
|
def test_ptrack_cluster_btree(self):
|
||||||
fname = self.id().split('.')[3]
|
fname = self.id().split('.')[3]
|
||||||
node = self.make_simple_node(base_dir="tmp_dirs/ptrack/{0}".format(fname),
|
node = self.make_simple_node(base_dir="tmp_dirs/ptrack/{0}".format(fname),
|
||||||
|
@ -161,6 +161,7 @@ class ProbackupTest(object):
|
|||||||
node.init(initdb_params=initdb_params)
|
node.init(initdb_params=initdb_params)
|
||||||
|
|
||||||
# Sane default parameters, not a shit with fsync = off from testgres
|
# Sane default parameters, not a shit with fsync = off from testgres
|
||||||
|
node.append_conf("postgresql.auto.conf", "{0} = {1}".format('shared_buffers', '10MB'))
|
||||||
node.append_conf("postgresql.auto.conf", "{0} = {1}".format('fsync', 'on'))
|
node.append_conf("postgresql.auto.conf", "{0} = {1}".format('fsync', 'on'))
|
||||||
node.append_conf("postgresql.auto.conf", "{0} = {1}".format('wal_level', 'minimal'))
|
node.append_conf("postgresql.auto.conf", "{0} = {1}".format('wal_level', 'minimal'))
|
||||||
|
|
||||||
@ -294,7 +295,7 @@ class ProbackupTest(object):
|
|||||||
|
|
||||||
def run_pb(self, command, async=False):
|
def run_pb(self, command, async=False):
|
||||||
try:
|
try:
|
||||||
# print [self.probackup_path] + command
|
#print [self.probackup_path] + command
|
||||||
if async is True:
|
if async is True:
|
||||||
return subprocess.Popen(
|
return subprocess.Popen(
|
||||||
[self.probackup_path] + command,
|
[self.probackup_path] + command,
|
||||||
@ -315,7 +316,9 @@ class ProbackupTest(object):
|
|||||||
return output
|
return output
|
||||||
else:
|
else:
|
||||||
# return backup ID
|
# return backup ID
|
||||||
return output.split()[2]
|
for line in output.splitlines():
|
||||||
|
if 'INFO: Backup' and 'completed' in line:
|
||||||
|
return line.split()[2]
|
||||||
else:
|
else:
|
||||||
return output
|
return output
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
@ -391,13 +394,17 @@ class ProbackupTest(object):
|
|||||||
body = body[::-1]
|
body = body[::-1]
|
||||||
# split string in list with string for every header element
|
# split string in list with string for every header element
|
||||||
header_split = re.split(" +", header)
|
header_split = re.split(" +", header)
|
||||||
# CRUNCH, remove last item, because it`s empty, like that ''
|
# Remove empty items
|
||||||
header_split.pop()
|
for i in header_split:
|
||||||
|
if i == '':
|
||||||
|
header_split.remove(i)
|
||||||
for backup_record in body:
|
for backup_record in body:
|
||||||
# split string in list with string for every backup record element
|
# split string in list with string for every backup record element
|
||||||
backup_record_split = re.split(" +", backup_record)
|
backup_record_split = re.split(" +", backup_record)
|
||||||
# CRUNCH, remove last item, because it`s empty, like that ''
|
# Remove empty items
|
||||||
backup_record_split.pop()
|
for i in backup_record_split:
|
||||||
|
if i == '':
|
||||||
|
backup_record_split.remove(i)
|
||||||
if len(header_split) != len(backup_record_split):
|
if len(header_split) != len(backup_record_split):
|
||||||
print warning.format(
|
print warning.format(
|
||||||
header=header, body=body,
|
header=header, body=body,
|
||||||
|
@ -15,6 +15,8 @@ class SimpleTest(ProbackupTest, unittest.TestCase):
|
|||||||
# clean_all()
|
# clean_all()
|
||||||
stop_all()
|
stop_all()
|
||||||
|
|
||||||
|
# @unittest.skip("skip")
|
||||||
|
# @unittest.expectedFailure
|
||||||
def test_ptrack_recovery(self):
|
def test_ptrack_recovery(self):
|
||||||
fname = self.id().split(".")[3]
|
fname = self.id().split(".")[3]
|
||||||
node = self.make_simple_node(base_dir="tmp_dirs/ptrack/{0}".format(fname),
|
node = self.make_simple_node(base_dir="tmp_dirs/ptrack/{0}".format(fname),
|
||||||
|
@ -15,6 +15,8 @@ class SimpleTest(ProbackupTest, unittest.TestCase):
|
|||||||
# clean_all()
|
# clean_all()
|
||||||
stop_all()
|
stop_all()
|
||||||
|
|
||||||
|
# @unittest.skip("skip")
|
||||||
|
# @unittest.expectedFailure
|
||||||
def test_ptrack_recovery(self):
|
def test_ptrack_recovery(self):
|
||||||
fname = self.id().split(".")[3]
|
fname = self.id().split(".")[3]
|
||||||
node = self.make_simple_node(base_dir="tmp_dirs/ptrack/{0}".format(fname),
|
node = self.make_simple_node(base_dir="tmp_dirs/ptrack/{0}".format(fname),
|
||||||
|
@ -12,7 +12,8 @@ class SimpleTest(ProbackupTest, unittest.TestCase):
|
|||||||
# clean_all()
|
# clean_all()
|
||||||
stop_all()
|
stop_all()
|
||||||
|
|
||||||
# @unittest.skip("123")
|
# @unittest.skip("skip")
|
||||||
|
# @unittest.expectedFailure
|
||||||
def test_ptrack_vacuum(self):
|
def test_ptrack_vacuum(self):
|
||||||
fname = self.id().split('.')[3]
|
fname = self.id().split('.')[3]
|
||||||
node = self.make_simple_node(base_dir='tmp_dirs/ptrack/{0}'.format(fname),
|
node = self.make_simple_node(base_dir='tmp_dirs/ptrack/{0}'.format(fname),
|
||||||
|
@ -13,6 +13,8 @@ class SimpleTest(ProbackupTest, unittest.TestCase):
|
|||||||
# clean_all()
|
# clean_all()
|
||||||
stop_all()
|
stop_all()
|
||||||
|
|
||||||
|
# @unittest.skip("skip")
|
||||||
|
# @unittest.expectedFailure
|
||||||
def test_ptrack_vacuum_bits_frozen(self):
|
def test_ptrack_vacuum_bits_frozen(self):
|
||||||
fname = self.id().split('.')[3]
|
fname = self.id().split('.')[3]
|
||||||
node = self.make_simple_node(base_dir='tmp_dirs/ptrack/{0}'.format(fname),
|
node = self.make_simple_node(base_dir='tmp_dirs/ptrack/{0}'.format(fname),
|
||||||
|
@ -13,6 +13,8 @@ class SimpleTest(ProbackupTest, unittest.TestCase):
|
|||||||
# clean_all()
|
# clean_all()
|
||||||
stop_all()
|
stop_all()
|
||||||
|
|
||||||
|
# @unittest.skip("skip")
|
||||||
|
# @unittest.expectedFailure
|
||||||
def test_ptrack_vacuum_bits_visibility(self):
|
def test_ptrack_vacuum_bits_visibility(self):
|
||||||
fname = self.id().split('.')[3]
|
fname = self.id().split('.')[3]
|
||||||
node = self.make_simple_node(base_dir='tmp_dirs/ptrack/{0}'.format(fname),
|
node = self.make_simple_node(base_dir='tmp_dirs/ptrack/{0}'.format(fname),
|
||||||
|
@ -5,17 +5,6 @@ from testgres import get_new_node, stop_all
|
|||||||
from os import path, open, lseek, read, close, O_RDONLY
|
from os import path, open, lseek, read, close, O_RDONLY
|
||||||
from .ptrack_helpers import ProbackupTest, idx_ptrack
|
from .ptrack_helpers import ProbackupTest, idx_ptrack
|
||||||
|
|
||||||
# res = node.execute('postgres', 'show fsync')
|
|
||||||
# print res[0][0]
|
|
||||||
# res = node.execute('postgres', 'show wal_level')
|
|
||||||
# print res[0][0]
|
|
||||||
# a = ProbackupTest
|
|
||||||
# res = node.execute('postgres', 'select 1')`
|
|
||||||
# self.assertEqual(len(res), 1)
|
|
||||||
# self.assertEqual(res[0][0], 1)
|
|
||||||
# node.stop()
|
|
||||||
# a = self.backup_dir(node)
|
|
||||||
|
|
||||||
|
|
||||||
class SimpleTest(ProbackupTest, unittest.TestCase):
|
class SimpleTest(ProbackupTest, unittest.TestCase):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
@ -25,9 +14,10 @@ class SimpleTest(ProbackupTest, unittest.TestCase):
|
|||||||
# clean_all()
|
# clean_all()
|
||||||
stop_all()
|
stop_all()
|
||||||
|
|
||||||
|
# @unittest.skip("skip")
|
||||||
|
# @unittest.expectedFailure
|
||||||
def test_ptrack_vacuum_full(self):
|
def test_ptrack_vacuum_full(self):
|
||||||
fname = self.id().split('.')[3]
|
fname = self.id().split('.')[3]
|
||||||
print '{0} started'.format(fname)
|
|
||||||
node = self.make_simple_node(base_dir='tmp_dirs/ptrack/{0}'.format(fname),
|
node = self.make_simple_node(base_dir='tmp_dirs/ptrack/{0}'.format(fname),
|
||||||
set_replication=True,
|
set_replication=True,
|
||||||
initdb_params=['--data-checksums', '-A trust'],
|
initdb_params=['--data-checksums', '-A trust'],
|
||||||
|
@ -13,6 +13,8 @@ class SimpleTest(ProbackupTest, unittest.TestCase):
|
|||||||
# clean_all()
|
# clean_all()
|
||||||
stop_all()
|
stop_all()
|
||||||
|
|
||||||
|
# @unittest.skip("skip")
|
||||||
|
# @unittest.expectedFailure
|
||||||
def test_ptrack_vacuum_truncate(self):
|
def test_ptrack_vacuum_truncate(self):
|
||||||
fname = self.id().split('.')[3]
|
fname = self.id().split('.')[3]
|
||||||
node = self.make_simple_node(base_dir='tmp_dirs/ptrack/{0}'.format(fname),
|
node = self.make_simple_node(base_dir='tmp_dirs/ptrack/{0}'.format(fname),
|
||||||
|
@ -11,19 +11,21 @@ from sys import exit
|
|||||||
class ReplicaTest(ProbackupTest, unittest.TestCase):
|
class ReplicaTest(ProbackupTest, unittest.TestCase):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(SomeTest, self).__init__(*args, **kwargs)
|
super(ReplicaTest, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def tearDownClass(cls):
|
def tearDownClass(cls):
|
||||||
stop_all()
|
stop_all()
|
||||||
|
|
||||||
|
# @unittest.skip("skip")
|
||||||
|
# @unittest.expectedFailure
|
||||||
def test_make_simple_replica(self):
|
def test_make_simple_replica(self):
|
||||||
"""
|
"""
|
||||||
make node with archiving, make stream backup,
|
make node with archiving, make stream backup,
|
||||||
get Recovery Time, try to make pitr to Recovery Time
|
get Recovery Time, try to make pitr to Recovery Time
|
||||||
"""
|
"""
|
||||||
fname = self.id().split('.')[3]
|
fname = self.id().split('.')[3]
|
||||||
master = self.make_simple_node(base_dir="tmp_dirs/pgpro561/{0}/master".format(fname),
|
master = self.make_simple_node(base_dir="tmp_dirs/replica/{0}/master".format(fname),
|
||||||
set_archiving=True,
|
set_archiving=True,
|
||||||
set_replication=True,
|
set_replication=True,
|
||||||
initdb_params=['--data-checksums'],
|
initdb_params=['--data-checksums'],
|
||||||
@ -31,30 +33,20 @@ class ReplicaTest(ProbackupTest, unittest.TestCase):
|
|||||||
)
|
)
|
||||||
master.start()
|
master.start()
|
||||||
|
|
||||||
slave = self.make_simple_node(base_dir="tmp_dirs/pgpro561/{0}/replica".format(fname),
|
slave = self.make_simple_node(base_dir="tmp_dirs/replica/{0}/slave".format(fname))
|
||||||
set_archiving=True,
|
|
||||||
set_replication=True,
|
|
||||||
initdb_params=['--data-checksums'],
|
|
||||||
pg_options={'wal_level': 'replica', 'max_wal_senders': '2'}
|
|
||||||
)
|
|
||||||
slave_port = slave.port
|
slave_port = slave.port
|
||||||
slave.cleanup()
|
slave.cleanup()
|
||||||
|
|
||||||
self.assertEqual(self.init_pb(master), six.b(""))
|
self.assertEqual(self.init_pb(master), six.b(""))
|
||||||
self.backup_pb(master, backup_type='full')
|
self.backup_pb(master, backup_type='full', options=['--stream'])
|
||||||
|
|
||||||
master.psql(
|
master.psql(
|
||||||
"postgres",
|
"postgres",
|
||||||
"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,256) i")
|
"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,256) i")
|
||||||
# for i in idx_ptrack:
|
|
||||||
# if idx_ptrack[i]['type'] == 'heap':
|
|
||||||
# continue
|
|
||||||
# master.psql("postgres", "create index {0} on {1} using {2}({3})".format(
|
|
||||||
# i, idx_ptrack[i]['relation'], idx_ptrack[i]['type'], idx_ptrack[i]['column']))
|
|
||||||
|
|
||||||
before = master.execute("postgres", "SELECT * FROM t_heap")
|
before = master.execute("postgres", "SELECT * FROM t_heap")
|
||||||
|
|
||||||
id = self.backup_pb(master, backup_type='page')
|
id = self.backup_pb(master, backup_type='page', options=['--stream'])
|
||||||
self.restore_pb(backup_dir=self.backup_dir(master), data_dir=slave.data_dir)
|
self.restore_pb(backup_dir=self.backup_dir(master), data_dir=slave.data_dir)
|
||||||
slave.append_conf('postgresql.auto.conf', 'port = {0}'.format(slave.port))
|
slave.append_conf('postgresql.auto.conf', 'port = {0}'.format(slave.port))
|
||||||
slave.append_conf('postgresql.auto.conf', 'hot_standby = on')
|
slave.append_conf('postgresql.auto.conf', 'hot_standby = on')
|
||||||
@ -66,3 +58,6 @@ class ReplicaTest(ProbackupTest, unittest.TestCase):
|
|||||||
|
|
||||||
after = slave.execute("postgres", "SELECT * FROM t_heap")
|
after = slave.execute("postgres", "SELECT * FROM t_heap")
|
||||||
self.assertEqual(before, after)
|
self.assertEqual(before, after)
|
||||||
|
|
||||||
|
self.assertEqual(self.init_pb(slave), six.b(""))
|
||||||
|
self.backup_pb(slave, backup_type='full', options=['--stream'])
|
||||||
|
@ -18,7 +18,8 @@ class RestoreTest(ProbackupTest, unittest.TestCase):
|
|||||||
def tearDownClass(cls):
|
def tearDownClass(cls):
|
||||||
stop_all()
|
stop_all()
|
||||||
|
|
||||||
# @unittest.skip("123")
|
# @unittest.skip("skip")
|
||||||
|
# @unittest.expectedFailure
|
||||||
def test_restore_full_to_latest(self):
|
def test_restore_full_to_latest(self):
|
||||||
"""recovery to latest from full backup"""
|
"""recovery to latest from full backup"""
|
||||||
fname = self.id().split('.')[3]
|
fname = self.id().split('.')[3]
|
||||||
@ -34,17 +35,14 @@ class RestoreTest(ProbackupTest, unittest.TestCase):
|
|||||||
pgbench.wait()
|
pgbench.wait()
|
||||||
pgbench.stdout.close()
|
pgbench.stdout.close()
|
||||||
before = node.execute("postgres", "SELECT * FROM pgbench_branches")
|
before = node.execute("postgres", "SELECT * FROM pgbench_branches")
|
||||||
with open(path.join(node.logs_dir, "backup_1.log"), "wb") as backup_log:
|
self.backup_pb(node)
|
||||||
backup_log.write(self.backup_pb(node, options=["--verbose"]))
|
|
||||||
|
|
||||||
node.stop({"-m": "immediate"})
|
node.stop({"-m": "immediate"})
|
||||||
node.cleanup()
|
node.cleanup()
|
||||||
|
|
||||||
# 1 - Test recovery from latest
|
# 1 - Test recovery from latest
|
||||||
# TODO WAITING FIX FOR RESTORE
|
self.assertTrue(six.b("INFO: Restore of backup") and
|
||||||
# self.assertIn(six.b("INFO: restore complete"),
|
six.b("completed.") in self.restore_pb(node, options=["-j", "4"]))
|
||||||
self.restore_pb(node, options=["-j", "4", "--verbose"])
|
|
||||||
# )
|
|
||||||
|
|
||||||
# 2 - Test that recovery.conf was created
|
# 2 - Test that recovery.conf was created
|
||||||
recovery_conf = path.join(node.data_dir, "recovery.conf")
|
recovery_conf = path.join(node.data_dir, "recovery.conf")
|
||||||
@ -70,24 +68,21 @@ class RestoreTest(ProbackupTest, unittest.TestCase):
|
|||||||
node.pgbench_init(scale=2)
|
node.pgbench_init(scale=2)
|
||||||
|
|
||||||
with open(path.join(node.logs_dir, "backup_1.log"), "wb") as backup_log:
|
with open(path.join(node.logs_dir, "backup_1.log"), "wb") as backup_log:
|
||||||
backup_log.write(self.backup_pb(node, options=["--verbose"]))
|
backup_log.write(self.backup_pb(node))
|
||||||
|
|
||||||
pgbench = node.pgbench(stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
pgbench = node.pgbench(stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
pgbench.wait()
|
pgbench.wait()
|
||||||
pgbench.stdout.close()
|
pgbench.stdout.close()
|
||||||
|
|
||||||
with open(path.join(node.logs_dir, "backup_2.log"), "wb") as backup_log:
|
self.backup_pb(node, backup_type="page")
|
||||||
backup_log.write(self.backup_pb(node, backup_type="page", options=["--verbose"]))
|
|
||||||
|
|
||||||
before = node.execute("postgres", "SELECT * FROM pgbench_branches")
|
before = node.execute("postgres", "SELECT * FROM pgbench_branches")
|
||||||
|
|
||||||
node.stop({"-m": "immediate"})
|
node.stop({"-m": "immediate"})
|
||||||
node.cleanup()
|
node.cleanup()
|
||||||
|
|
||||||
# TODO WAITING FIX FOR RESTORE
|
self.assertTrue(six.b("INFO: Restore of backup") and
|
||||||
# self.assertIn(six.b("INFO: restore complete"),
|
six.b("completed.") in self.restore_pb(node, options=["-j", "4"]))
|
||||||
self.restore_pb(node, options=["-j", "4", "--verbose"])
|
|
||||||
# )
|
|
||||||
|
|
||||||
node.start({"-t": "600"})
|
node.start({"-t": "600"})
|
||||||
|
|
||||||
@ -110,17 +105,14 @@ class RestoreTest(ProbackupTest, unittest.TestCase):
|
|||||||
|
|
||||||
before = node.execute("postgres", "SELECT * FROM pgbench_branches")
|
before = node.execute("postgres", "SELECT * FROM pgbench_branches")
|
||||||
|
|
||||||
with open(path.join(node.logs_dir, "backup_1.log"), "wb") as backup_log:
|
self.backup_pb(node, backup_type="full")
|
||||||
backup_log.write(self.backup_pb(node, backup_type="full", options=["--verbose"]))
|
|
||||||
|
|
||||||
target_tli = int(node.get_control_data()[six.b("Latest checkpoint's TimeLineID")])
|
target_tli = int(node.get_control_data()[six.b("Latest checkpoint's TimeLineID")])
|
||||||
node.stop({"-m": "immediate"})
|
node.stop({"-m": "immediate"})
|
||||||
node.cleanup()
|
node.cleanup()
|
||||||
|
|
||||||
# TODO WAITING FIX FOR RESTORE
|
self.assertTrue(six.b("INFO: Restore of backup") and
|
||||||
# self.assertIn(six.b("INFO: restore complete"),
|
six.b("completed.") in self.restore_pb(node, options=["-j", "4"]))
|
||||||
self.restore_pb(node, options=["-j", "4", "--verbose"])
|
|
||||||
# )
|
|
||||||
|
|
||||||
node.start({"-t": "600"})
|
node.start({"-t": "600"})
|
||||||
|
|
||||||
@ -128,17 +120,14 @@ class RestoreTest(ProbackupTest, unittest.TestCase):
|
|||||||
pgbench.wait()
|
pgbench.wait()
|
||||||
pgbench.stdout.close()
|
pgbench.stdout.close()
|
||||||
|
|
||||||
with open(path.join(node.logs_dir, "backup_2.log"), "wb") as backup_log:
|
self.backup_pb(node, backup_type="full")
|
||||||
backup_log.write(self.backup_pb(node, backup_type="full", options=["--verbose"]))
|
|
||||||
|
|
||||||
node.stop({"-m": "immediate"})
|
node.stop({"-m": "immediate"})
|
||||||
node.cleanup()
|
node.cleanup()
|
||||||
|
|
||||||
# TODO WAITING FIX FOR RESTORE
|
self.assertTrue(six.b("INFO: Restore of backup") and
|
||||||
# self.assertIn(six.b("INFO: restore complete"),
|
six.b("completed.") in self.restore_pb(node,
|
||||||
self.restore_pb(node,
|
options=["-j", "4", "--timeline=%i" % target_tli]))
|
||||||
options=["-j", "4", "--verbose", "--timeline=%i" % target_tli])
|
|
||||||
# )
|
|
||||||
|
|
||||||
recovery_target_timeline = self.get_recovery_conf(node)["recovery_target_timeline"]
|
recovery_target_timeline = self.get_recovery_conf(node)["recovery_target_timeline"]
|
||||||
self.assertEqual(int(recovery_target_timeline), target_tli)
|
self.assertEqual(int(recovery_target_timeline), target_tli)
|
||||||
@ -164,8 +153,7 @@ class RestoreTest(ProbackupTest, unittest.TestCase):
|
|||||||
|
|
||||||
before = node.execute("postgres", "SELECT * FROM pgbench_branches")
|
before = node.execute("postgres", "SELECT * FROM pgbench_branches")
|
||||||
|
|
||||||
with open(path.join(node.logs_dir, "backup_1.log"), "wb") as backup_log:
|
self.backup_pb(node, backup_type="full")
|
||||||
backup_log.write(self.backup_pb(node, backup_type="full", options=["--verbose"]))
|
|
||||||
|
|
||||||
target_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
target_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
pgbench = node.pgbench(stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
pgbench = node.pgbench(stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
@ -175,11 +163,9 @@ class RestoreTest(ProbackupTest, unittest.TestCase):
|
|||||||
node.stop({"-m": "immediate"})
|
node.stop({"-m": "immediate"})
|
||||||
node.cleanup()
|
node.cleanup()
|
||||||
|
|
||||||
# TODO WAITING FIX FOR RESTORE
|
self.assertTrue(six.b("INFO: Restore of backup") and
|
||||||
# self.assertIn(six.b("INFO: restore complete"),
|
six.b("completed.") in self.restore_pb(node,
|
||||||
self.restore_pb(node,
|
options=["-j", "4", '--time="%s"' % target_time]))
|
||||||
options=["-j", "4", "--verbose", '--time="%s"' % target_time])
|
|
||||||
# )
|
|
||||||
|
|
||||||
node.start({"-t": "600"})
|
node.start({"-t": "600"})
|
||||||
|
|
||||||
@ -203,8 +189,7 @@ class RestoreTest(ProbackupTest, unittest.TestCase):
|
|||||||
con.execute("CREATE TABLE tbl0005 (a text)")
|
con.execute("CREATE TABLE tbl0005 (a text)")
|
||||||
con.commit()
|
con.commit()
|
||||||
|
|
||||||
with open(path.join(node.logs_dir, "backup_1.log"), "wb") as backup_log:
|
self.backup_pb(node, backup_type="full")
|
||||||
backup_log.write(self.backup_pb(node, backup_type="full", options=["--verbose"]))
|
|
||||||
|
|
||||||
pgbench = node.pgbench(stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
pgbench = node.pgbench(stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
pgbench.wait()
|
pgbench.wait()
|
||||||
@ -228,11 +213,9 @@ class RestoreTest(ProbackupTest, unittest.TestCase):
|
|||||||
node.stop({"-m": "fast"})
|
node.stop({"-m": "fast"})
|
||||||
node.cleanup()
|
node.cleanup()
|
||||||
|
|
||||||
# TODO WAITING FIX FOR RESTORE
|
self.assertTrue(six.b("INFO: Restore of backup") and
|
||||||
# self.assertIn(six.b("INFO: restore complete"),
|
six.b("completed.") in self.restore_pb(node,
|
||||||
self.restore_pb(node,
|
options=["-j", "4", '--xid=%s' % target_xid]))
|
||||||
options=["-j", "4", "--verbose", '--xid=%s' % target_xid])
|
|
||||||
# )
|
|
||||||
|
|
||||||
node.start({"-t": "600"})
|
node.start({"-t": "600"})
|
||||||
|
|
||||||
@ -261,25 +244,21 @@ class RestoreTest(ProbackupTest, unittest.TestCase):
|
|||||||
node.append_conf("postgresql.conf", "ptrack_enable = on")
|
node.append_conf("postgresql.conf", "ptrack_enable = on")
|
||||||
node.restart()
|
node.restart()
|
||||||
|
|
||||||
with open(path.join(node.logs_dir, "backup_1.log"), "wb") as backup_log:
|
self.backup_pb(node, backup_type="full")
|
||||||
backup_log.write(self.backup_pb(node, backup_type="full", options=["--verbose"]))
|
|
||||||
|
|
||||||
pgbench = node.pgbench(stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
pgbench = node.pgbench(stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
pgbench.wait()
|
pgbench.wait()
|
||||||
pgbench.stdout.close()
|
pgbench.stdout.close()
|
||||||
|
|
||||||
with open(path.join(node.logs_dir, "backup_2.log"), "wb") as backup_log:
|
self.backup_pb(node, backup_type="ptrack")
|
||||||
backup_log.write(self.backup_pb(node, backup_type="ptrack", options=["--verbose"]))
|
|
||||||
|
|
||||||
before = node.execute("postgres", "SELECT * FROM pgbench_branches")
|
before = node.execute("postgres", "SELECT * FROM pgbench_branches")
|
||||||
|
|
||||||
node.stop({"-m": "immediate"})
|
node.stop({"-m": "immediate"})
|
||||||
node.cleanup()
|
node.cleanup()
|
||||||
|
|
||||||
# TODO WAITING FIX FOR RESTORE
|
self.assertTrue(six.b("INFO: Restore of backup") and
|
||||||
# self.assertIn(six.b("INFO: restore complete"),
|
six.b("completed.") in self.restore_pb(node, options=["-j", "4"]))
|
||||||
self.restore_pb(node, options=["-j", "4", "--verbose"])
|
|
||||||
# )
|
|
||||||
|
|
||||||
node.start({"-t": "600"})
|
node.start({"-t": "600"})
|
||||||
|
|
||||||
@ -308,32 +287,27 @@ class RestoreTest(ProbackupTest, unittest.TestCase):
|
|||||||
node.append_conf("postgresql.conf", "ptrack_enable = on")
|
node.append_conf("postgresql.conf", "ptrack_enable = on")
|
||||||
node.restart()
|
node.restart()
|
||||||
|
|
||||||
with open(path.join(node.logs_dir, "backup_1.log"), "wb") as backup_log:
|
self.backup_pb(node, backup_type="full")
|
||||||
backup_log.write(self.backup_pb(node, backup_type="full", options=["--verbose"]))
|
|
||||||
|
|
||||||
pgbench = node.pgbench(stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
pgbench = node.pgbench(stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
pgbench.wait()
|
pgbench.wait()
|
||||||
pgbench.stdout.close()
|
pgbench.stdout.close()
|
||||||
|
|
||||||
with open(path.join(node.logs_dir, "backup_2.log"), "wb") as backup_log:
|
self.backup_pb(node, backup_type="ptrack")
|
||||||
backup_log.write(self.backup_pb(node, backup_type="ptrack", options=["--verbose"]))
|
|
||||||
|
|
||||||
pgbench = node.pgbench(stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
pgbench = node.pgbench(stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
pgbench.wait()
|
pgbench.wait()
|
||||||
pgbench.stdout.close()
|
pgbench.stdout.close()
|
||||||
|
|
||||||
with open(path.join(node.logs_dir, "backup_3.log"), "wb") as backup_log:
|
self.backup_pb(node, backup_type="ptrack")
|
||||||
backup_log.write(self.backup_pb(node, backup_type="ptrack", options=["--verbose"]))
|
|
||||||
|
|
||||||
before = node.execute("postgres", "SELECT * FROM pgbench_branches")
|
before = node.execute("postgres", "SELECT * FROM pgbench_branches")
|
||||||
|
|
||||||
node.stop({"-m": "immediate"})
|
node.stop({"-m": "immediate"})
|
||||||
node.cleanup()
|
node.cleanup()
|
||||||
|
|
||||||
# TODO WAITING FIX FOR RESTORE
|
self.assertTrue(six.b("INFO: Restore of backup") and
|
||||||
# self.assertIn(six.b("INFO: restore complete"),
|
six.b("completed.") in self.restore_pb(node, options=["-j", "4"]))
|
||||||
self.restore_pb(node, options=["-j", "4", "--verbose"])
|
|
||||||
# )
|
|
||||||
|
|
||||||
node.start({"-t": "600"})
|
node.start({"-t": "600"})
|
||||||
|
|
||||||
@ -359,25 +333,21 @@ class RestoreTest(ProbackupTest, unittest.TestCase):
|
|||||||
self.skipTest("ptrack not supported")
|
self.skipTest("ptrack not supported")
|
||||||
return
|
return
|
||||||
|
|
||||||
with open(path.join(node.logs_dir, "backup_1.log"), "wb") as backup_log:
|
self.backup_pb(node, backup_type="full", options=["--stream"])
|
||||||
backup_log.write(self.backup_pb(node, backup_type="full", options=["--verbose", "--stream"]))
|
|
||||||
|
|
||||||
pgbench = node.pgbench(stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
pgbench = node.pgbench(stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
pgbench.wait()
|
pgbench.wait()
|
||||||
pgbench.stdout.close()
|
pgbench.stdout.close()
|
||||||
|
|
||||||
with open(path.join(node.logs_dir, "backup_2.log"), "wb") as backup_log:
|
self.backup_pb(node, backup_type="ptrack", options=["--stream"])
|
||||||
backup_log.write(self.backup_pb(node, backup_type="ptrack", options=["--verbose", "--stream"]))
|
|
||||||
|
|
||||||
before = node.execute("postgres", "SELECT * FROM pgbench_branches")
|
before = node.execute("postgres", "SELECT * FROM pgbench_branches")
|
||||||
|
|
||||||
node.stop({"-m": "immediate"})
|
node.stop({"-m": "immediate"})
|
||||||
node.cleanup()
|
node.cleanup()
|
||||||
|
|
||||||
# TODO WAITING FIX FOR RESTORE
|
self.assertTrue(six.b("INFO: Restore of backup") and
|
||||||
# self.assertIn(six.b("INFO: restore complete"),
|
six.b("completed.") in self.restore_pb(node, options=["-j", "4"]))
|
||||||
self.restore_pb(node, options=["-j", "4", "--verbose"])
|
|
||||||
# )
|
|
||||||
|
|
||||||
node.start({"-t": "600"})
|
node.start({"-t": "600"})
|
||||||
|
|
||||||
@ -406,8 +376,7 @@ class RestoreTest(ProbackupTest, unittest.TestCase):
|
|||||||
return
|
return
|
||||||
node.restart()
|
node.restart()
|
||||||
|
|
||||||
with open(path.join(node.logs_dir, "backup_1.log"), "wb") as backup_log:
|
self.backup_pb(node, backup_type="full")
|
||||||
backup_log.write(self.backup_pb(node, backup_type="full", options=["--verbose"]))
|
|
||||||
|
|
||||||
pgbench = node.pgbench(
|
pgbench = node.pgbench(
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
@ -415,8 +384,7 @@ class RestoreTest(ProbackupTest, unittest.TestCase):
|
|||||||
options=["-c", "4", "-T", "8"]
|
options=["-c", "4", "-T", "8"]
|
||||||
)
|
)
|
||||||
|
|
||||||
with open(path.join(node.logs_dir, "backup_2.log"), "wb") as backup_log:
|
self.backup_pb(node, backup_type="ptrack", options=["--stream"])
|
||||||
backup_log.write(self.backup_pb(node, backup_type="ptrack", options=["--verbose", "--stream"]))
|
|
||||||
|
|
||||||
pgbench.wait()
|
pgbench.wait()
|
||||||
pgbench.stdout.close()
|
pgbench.stdout.close()
|
||||||
@ -430,10 +398,8 @@ class RestoreTest(ProbackupTest, unittest.TestCase):
|
|||||||
|
|
||||||
self.wrong_wal_clean(node, wal_segment_size)
|
self.wrong_wal_clean(node, wal_segment_size)
|
||||||
|
|
||||||
# TODO WAITING FIX FOR RESTORE
|
self.assertTrue(six.b("INFO: Restore of backup") and
|
||||||
# self.assertIn(six.b("INFO: restore complete"),
|
six.b("completed.") in self.restore_pb(node, options=["-j", "4"]))
|
||||||
self.restore_pb(node, options=["-j", "4", "--verbose"])
|
|
||||||
# )
|
|
||||||
|
|
||||||
node.start({"-t": "600"})
|
node.start({"-t": "600"})
|
||||||
|
|
||||||
@ -471,14 +437,12 @@ class RestoreTest(ProbackupTest, unittest.TestCase):
|
|||||||
options=["-c", "4", "-T", "8"]
|
options=["-c", "4", "-T", "8"]
|
||||||
)
|
)
|
||||||
|
|
||||||
with open(path.join(node.logs_dir, "backup_1.log"), "wb") as backup_log:
|
self.backup_pb(node, backup_type="full")
|
||||||
backup_log.write(self.backup_pb(node, backup_type="full", options=["--verbose"]))
|
|
||||||
|
|
||||||
pgbench.wait()
|
pgbench.wait()
|
||||||
pgbench.stdout.close()
|
pgbench.stdout.close()
|
||||||
|
|
||||||
with open(path.join(node.logs_dir, "backup_2.log"), "wb") as backup_log:
|
self.backup_pb(node, backup_type="ptrack", options=["--stream"])
|
||||||
backup_log.write(self.backup_pb(node, backup_type="ptrack", options=["--verbose", "--stream"]))
|
|
||||||
|
|
||||||
bbalance = node.execute("postgres", "SELECT sum(bbalance) FROM pgbench_branches")
|
bbalance = node.execute("postgres", "SELECT sum(bbalance) FROM pgbench_branches")
|
||||||
delta = node.execute("postgres", "SELECT sum(delta) FROM pgbench_history")
|
delta = node.execute("postgres", "SELECT sum(delta) FROM pgbench_history")
|
||||||
@ -489,10 +453,8 @@ class RestoreTest(ProbackupTest, unittest.TestCase):
|
|||||||
node.cleanup()
|
node.cleanup()
|
||||||
self.wrong_wal_clean(node, wal_segment_size)
|
self.wrong_wal_clean(node, wal_segment_size)
|
||||||
|
|
||||||
# TODO WAITING FIX FOR RESTORE
|
self.assertTrue(six.b("INFO: Restore of backup") and
|
||||||
# self.assertIn(six.b("INFO: restore complete"),
|
six.b("completed.") in self.restore_pb(node, options=["-j", "4"]))
|
||||||
self.restore_pb(node, options=["-j", "4", "--verbose"])
|
|
||||||
# )
|
|
||||||
|
|
||||||
node.start({"-t": "600"})
|
node.start({"-t": "600"})
|
||||||
|
|
||||||
@ -518,8 +480,7 @@ class RestoreTest(ProbackupTest, unittest.TestCase):
|
|||||||
con.execute("CREATE TABLE tbl0005 (a text)")
|
con.execute("CREATE TABLE tbl0005 (a text)")
|
||||||
con.commit()
|
con.commit()
|
||||||
|
|
||||||
with open(path.join(node.logs_dir, "backup_1.log"), "wb") as backup_log:
|
self.backup_pb(node, backup_type="full")
|
||||||
backup_log.write(self.backup_pb(node, backup_type="full", options=["--verbose"]))
|
|
||||||
|
|
||||||
pgbench = node.pgbench(stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
pgbench = node.pgbench(stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
pgbench.wait()
|
pgbench.wait()
|
||||||
@ -543,15 +504,12 @@ class RestoreTest(ProbackupTest, unittest.TestCase):
|
|||||||
node.stop({"-m": "fast"})
|
node.stop({"-m": "fast"})
|
||||||
node.cleanup()
|
node.cleanup()
|
||||||
|
|
||||||
# TODO WAITING FIX FOR RESTORE
|
self.assertTrue(six.b("INFO: Restore of backup") and
|
||||||
# self.assertIn(six.b("INFO: restore complete"),
|
six.b("completed.") in self.restore_pb(node,
|
||||||
self.restore_pb(node,
|
|
||||||
options=[
|
options=[
|
||||||
"-j", "4",
|
"-j", "4",
|
||||||
"--verbose",
|
|
||||||
'--xid=%s' % target_xid,
|
'--xid=%s' % target_xid,
|
||||||
"--inclusive=false"])
|
"--inclusive=false"]))
|
||||||
# )
|
|
||||||
|
|
||||||
node.start({"-t": "600"})
|
node.start({"-t": "600"})
|
||||||
|
|
||||||
@ -590,33 +548,27 @@ class RestoreTest(ProbackupTest, unittest.TestCase):
|
|||||||
node.stop()
|
node.stop()
|
||||||
try:
|
try:
|
||||||
self.restore_pb(node)
|
self.restore_pb(node)
|
||||||
# we should die here because exception is what we expect to happen
|
assertEqual(1, 0, 'Error is expected because restore destination is not empty')
|
||||||
exit(1)
|
|
||||||
except ProbackupException, e:
|
except ProbackupException, e:
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
e.message,
|
e.message,
|
||||||
'ERROR: restore destination is not empty: "{0}"\n'.format(node.data_dir)
|
'ERROR: restore destination is not empty: "{0}"\n'.format(node.data_dir))
|
||||||
)
|
|
||||||
|
|
||||||
# 2 - Try to restore to existing tablespace directory
|
# 2 - Try to restore to existing tablespace directory
|
||||||
shutil.rmtree(node.data_dir)
|
shutil.rmtree(node.data_dir)
|
||||||
try:
|
try:
|
||||||
self.restore_pb(node)
|
self.restore_pb(node)
|
||||||
# we should die here because exception is what we expect to happen
|
assertEqual(1, 0, 'Error is expected because restore tablespace destination is not empty')
|
||||||
exit(1)
|
|
||||||
except ProbackupException, e:
|
except ProbackupException, e:
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
e.message,
|
e.message,
|
||||||
'ERROR: restore tablespace destination is not empty: "{0}"\n'.format(tblspc_path)
|
'ERROR: restore tablespace destination is not empty: "{0}"\n'.format(tblspc_path))
|
||||||
)
|
|
||||||
|
|
||||||
# 3 - Restore using tablespace-mapping
|
# 3 - Restore using tablespace-mapping
|
||||||
tblspc_path_new = path.join(node.base_dir, "tblspc_new")
|
tblspc_path_new = path.join(node.base_dir, "tblspc_new")
|
||||||
# TODO WAITING FIX FOR RESTORE
|
self.assertTrue(six.b("INFO: Restore of backup") and
|
||||||
# self.assertIn(six.b("INFO: restore complete."),
|
six.b("completed.") in self.restore_pb(node,
|
||||||
self.restore_pb(node,
|
options=["-T", "%s=%s" % (tblspc_path, tblspc_path_new)]))
|
||||||
options=["-T", "%s=%s" % (tblspc_path, tblspc_path_new)])
|
|
||||||
# )
|
|
||||||
|
|
||||||
node.start()
|
node.start()
|
||||||
id = node.execute("postgres", "SELECT id FROM test")
|
id = node.execute("postgres", "SELECT id FROM test")
|
||||||
@ -636,11 +588,10 @@ class RestoreTest(ProbackupTest, unittest.TestCase):
|
|||||||
node.stop()
|
node.stop()
|
||||||
node.cleanup()
|
node.cleanup()
|
||||||
tblspc_path_page = path.join(node.base_dir, "tblspc_page")
|
tblspc_path_page = path.join(node.base_dir, "tblspc_page")
|
||||||
# TODO WAITING FIX FOR RESTORE
|
|
||||||
# self.assertIn(six.b("INFO: restore complete."),
|
self.assertTrue(six.b("INFO: Restore of backup") and
|
||||||
self.restore_pb(node,
|
six.b("completed.") in self.restore_pb(node,
|
||||||
options=["-T", "%s=%s" % (tblspc_path_new, tblspc_path_page)])
|
options=["-T", "%s=%s" % (tblspc_path_new, tblspc_path_page)]))
|
||||||
# )
|
|
||||||
|
|
||||||
node.start()
|
node.start()
|
||||||
id = node.execute("postgres", "SELECT id FROM test OFFSET 1")
|
id = node.execute("postgres", "SELECT id FROM test OFFSET 1")
|
||||||
@ -696,13 +647,10 @@ class RestoreTest(ProbackupTest, unittest.TestCase):
|
|||||||
node.cleanup()
|
node.cleanup()
|
||||||
|
|
||||||
tblspc_path_new = path.join(node.base_dir, "tblspc_new")
|
tblspc_path_new = path.join(node.base_dir, "tblspc_new")
|
||||||
# exit(1)
|
|
||||||
# TODO WAITING FIX FOR RESTORE
|
self.assertTrue(six.b("INFO: Restore of backup") and
|
||||||
# self.assertIn(six.b("INFO: restore complete."),
|
six.b("completed.") in self.restore_pb(node,
|
||||||
self.restore_pb(node,
|
options=["-T", "%s=%s" % (tblspc_path, tblspc_path_new)]))
|
||||||
options=["-T", "%s=%s" % (tblspc_path, tblspc_path_new)])
|
|
||||||
# )
|
|
||||||
# Check tables
|
|
||||||
node.start()
|
node.start()
|
||||||
|
|
||||||
count = node.execute("postgres", "SELECT count(*) FROM tbl")
|
count = node.execute("postgres", "SELECT count(*) FROM tbl")
|
||||||
@ -732,7 +680,10 @@ class RestoreTest(ProbackupTest, unittest.TestCase):
|
|||||||
node.pg_ctl('stop', {'-m': 'immediate', '-D': '{0}'.format(node.data_dir)})
|
node.pg_ctl('stop', {'-m': 'immediate', '-D': '{0}'.format(node.data_dir)})
|
||||||
node.cleanup()
|
node.cleanup()
|
||||||
|
|
||||||
self.restore_pb(node, options=['--time="{0}"'.format(recovery_time)])
|
self.assertTrue(six.b("INFO: Restore of backup") and
|
||||||
|
six.b("completed.") in self.restore_pb(
|
||||||
|
node, options=['--time="{0}"'.format(recovery_time)]))
|
||||||
|
|
||||||
node.start({"-t": "600"})
|
node.start({"-t": "600"})
|
||||||
self.assertEqual(True, node.status())
|
self.assertEqual(True, node.status())
|
||||||
node.stop()
|
node.stop()
|
||||||
@ -757,9 +708,11 @@ class RestoreTest(ProbackupTest, unittest.TestCase):
|
|||||||
node.pg_ctl('stop', {'-m': 'immediate', '-D': '{0}'.format(node.data_dir)})
|
node.pg_ctl('stop', {'-m': 'immediate', '-D': '{0}'.format(node.data_dir)})
|
||||||
node.cleanup()
|
node.cleanup()
|
||||||
recovery_time = self.show_pb(node, id=id)['recovery-time']
|
recovery_time = self.show_pb(node, id=id)['recovery-time']
|
||||||
self.restore_pb(node,
|
|
||||||
options=["-j", "4", '--time="{0}"'.format(recovery_time)]
|
self.assertTrue(six.b("INFO: Restore of backup") and
|
||||||
)
|
six.b("completed.") in self.restore_pb(node,
|
||||||
|
options=["-j", "4", '--time="{0}"'.format(recovery_time)]))
|
||||||
|
|
||||||
node.start({"-t": "600"})
|
node.start({"-t": "600"})
|
||||||
|
|
||||||
res = node.psql("postgres", 'select * from t_heap')
|
res = node.psql("postgres", 'select * from t_heap')
|
||||||
|
@ -15,7 +15,8 @@ class RetentionTest(ProbackupTest, unittest.TestCase):
|
|||||||
def tearDownClass(cls):
|
def tearDownClass(cls):
|
||||||
stop_all()
|
stop_all()
|
||||||
|
|
||||||
# @unittest.skip("123")
|
# @unittest.skip("skip")
|
||||||
|
# @unittest.expectedFailure
|
||||||
def test_retention_redundancy_1(self):
|
def test_retention_redundancy_1(self):
|
||||||
"""purge backups using redundancy-based retention policy"""
|
"""purge backups using redundancy-based retention policy"""
|
||||||
fname = self.id().split('.')[3]
|
fname = self.id().split('.')[3]
|
||||||
|
@ -15,6 +15,8 @@ class OptionTest(ProbackupTest, unittest.TestCase):
|
|||||||
def tearDownClass(cls):
|
def tearDownClass(cls):
|
||||||
stop_all()
|
stop_all()
|
||||||
|
|
||||||
|
# @unittest.skip("skip")
|
||||||
|
# @unittest.expectedFailure
|
||||||
def show_test_1(self):
|
def show_test_1(self):
|
||||||
"""Status DONE and OK"""
|
"""Status DONE and OK"""
|
||||||
fname = self.id().split('.')[3]
|
fname = self.id().split('.')[3]
|
||||||
|
@ -13,43 +13,13 @@ class ValidateTest(ProbackupTest, unittest.TestCase):
|
|||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(ValidateTest, self).__init__(*args, **kwargs)
|
super(ValidateTest, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
# @classmethod
|
@classmethod
|
||||||
# def tearDownClass(cls):
|
def tearDownClass(cls):
|
||||||
# try:
|
stop_all()
|
||||||
# stop_all()
|
|
||||||
# except:
|
|
||||||
# pass
|
|
||||||
|
|
||||||
# @unittest.skip("123")
|
# @unittest.skip("skip")
|
||||||
def test_validate_time(self):
|
# @unittest.expectedFailure
|
||||||
"""recovery to latest from full backup. Expect to Fail"""
|
def test_validate_wal_unreal_values(self):
|
||||||
fname = self.id().split('.')[3]
|
|
||||||
node = self.make_simple_node(base_dir="tmp_dirs/validate/{0}".format(fname),
|
|
||||||
set_archiving=True,
|
|
||||||
initdb_params=['--data-checksums'],
|
|
||||||
pg_options={'wal_level': 'replica'}
|
|
||||||
)
|
|
||||||
node.start()
|
|
||||||
|
|
||||||
node.pgbench_init(scale=2)
|
|
||||||
pgbench = node.pgbench(
|
|
||||||
stdout=subprocess.PIPE,
|
|
||||||
stderr=subprocess.STDOUT,
|
|
||||||
options=["-c", "4", "-T", "10"]
|
|
||||||
)
|
|
||||||
pgbench.wait()
|
|
||||||
pgbench.stdout.close()
|
|
||||||
|
|
||||||
self.assertEqual(self.init_pb(node), six.b(""))
|
|
||||||
id = self.backup_pb(node)
|
|
||||||
recovery_time = self.show_pb(node, id=id)['recovery-time']
|
|
||||||
|
|
||||||
self.assertIn(six.b("INFO: backup validation completed successfully on"),
|
|
||||||
self.validate_pb(node, options=["--time='{0}'".format(recovery_time)]))
|
|
||||||
node.stop()
|
|
||||||
|
|
||||||
# @unittest.skip("123")
|
|
||||||
def test_validate_wal_1(self):
|
|
||||||
"""recovery to latest from full backup"""
|
"""recovery to latest from full backup"""
|
||||||
fname = self.id().split('.')[3]
|
fname = self.id().split('.')[3]
|
||||||
node = self.make_simple_node(base_dir="tmp_dirs/validate/{0}".format(fname),
|
node = self.make_simple_node(base_dir="tmp_dirs/validate/{0}".format(fname),
|
||||||
@ -65,8 +35,7 @@ class ValidateTest(ProbackupTest, unittest.TestCase):
|
|||||||
con.execute("CREATE TABLE tbl0005 (a text)")
|
con.execute("CREATE TABLE tbl0005 (a text)")
|
||||||
con.commit()
|
con.commit()
|
||||||
|
|
||||||
with open(os.path.join(node.logs_dir, "backup_1.log"), "wb") as backup_log:
|
self.backup_pb(node)
|
||||||
backup_log.write(self.backup_pb(node, options=["--verbose"]))
|
|
||||||
|
|
||||||
node.pgbench_init(scale=2)
|
node.pgbench_init(scale=2)
|
||||||
pgbench = node.pgbench(
|
pgbench = node.pgbench(
|
||||||
@ -78,7 +47,7 @@ class ValidateTest(ProbackupTest, unittest.TestCase):
|
|||||||
pgbench.wait()
|
pgbench.wait()
|
||||||
pgbench.stdout.close()
|
pgbench.stdout.close()
|
||||||
|
|
||||||
id_backup = self.show_pb(node)[0]['ID']
|
backup_id = self.show_pb(node)[0]['ID']
|
||||||
target_time = self.show_pb(node)[0]['Recovery time']
|
target_time = self.show_pb(node)[0]['Recovery time']
|
||||||
after_backup_time = datetime.now()
|
after_backup_time = datetime.now()
|
||||||
|
|
||||||
@ -91,24 +60,19 @@ class ValidateTest(ProbackupTest, unittest.TestCase):
|
|||||||
self.validate_pb(node, options=["--time='{:%Y-%m-%d %H:%M:%S}'".format(
|
self.validate_pb(node, options=["--time='{:%Y-%m-%d %H:%M:%S}'".format(
|
||||||
after_backup_time - timedelta(days=2))])
|
after_backup_time - timedelta(days=2))])
|
||||||
# we should die here because exception is what we expect to happen
|
# we should die here because exception is what we expect to happen
|
||||||
exit(1)
|
self.assertEqual(1, 0, "Error in validation is expected because of validation of unreal time")
|
||||||
except ProbackupException, e:
|
except ProbackupException, e:
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
e.message,
|
e.message,
|
||||||
'ERROR: Full backup satisfying target options is not found.\n'
|
'ERROR: Full backup satisfying target options is not found.\n')
|
||||||
)
|
|
||||||
|
|
||||||
# Validate to unreal time #2
|
# Validate to unreal time #2
|
||||||
try:
|
try:
|
||||||
self.validate_pb(node, options=["--time='{:%Y-%m-%d %H:%M:%S}'".format(
|
self.validate_pb(node, options=["--time='{:%Y-%m-%d %H:%M:%S}'".format(
|
||||||
after_backup_time + timedelta(days=2))])
|
after_backup_time + timedelta(days=2))])
|
||||||
# we should die here because exception is what we expect to happen
|
self.assertEqual(1, 0, "Error in validation is expected because of validation unreal time")
|
||||||
exit(1)
|
|
||||||
except ProbackupException, e:
|
except ProbackupException, e:
|
||||||
self.assertEqual(
|
self.assertEqual(True, 'ERROR: not enough WAL records to time' in e.message)
|
||||||
True,
|
|
||||||
'ERROR: not enough WAL records to time' in e.message
|
|
||||||
)
|
|
||||||
|
|
||||||
# Validate to real xid
|
# Validate to real xid
|
||||||
target_xid = None
|
target_xid = None
|
||||||
@ -124,19 +88,32 @@ class ValidateTest(ProbackupTest, unittest.TestCase):
|
|||||||
# Validate to unreal xid
|
# Validate to unreal xid
|
||||||
try:
|
try:
|
||||||
self.validate_pb(node, options=["--xid=%d" % (int(target_xid) + 1000)])
|
self.validate_pb(node, options=["--xid=%d" % (int(target_xid) + 1000)])
|
||||||
# we should die here because exception is what we expect to happen
|
self.assertEqual(1, 0, "Error in validation is expected because of validation of unreal xid")
|
||||||
exit(1)
|
|
||||||
except ProbackupException, e:
|
except ProbackupException, e:
|
||||||
self.assertEqual(
|
self.assertEqual(True, 'ERROR: not enough WAL records to xid' in e.message)
|
||||||
True,
|
|
||||||
'ERROR: not enough WAL records to xid' in e.message
|
|
||||||
)
|
|
||||||
|
|
||||||
# Validate with backup ID
|
# Validate with backup ID
|
||||||
self.assertIn(six.b("INFO: backup validation completed successfully on"),
|
self.assertIn(six.b("INFO: backup validation completed successfully on"),
|
||||||
self.validate_pb(node, id_backup))
|
self.validate_pb(node, backup_id))
|
||||||
|
|
||||||
# Validate broken WAL
|
def test_validate_broken_wal_1(self):
|
||||||
|
"""recovery to latest from full backup"""
|
||||||
|
fname = self.id().split('.')[3]
|
||||||
|
node = self.make_simple_node(base_dir="tmp_dirs/validate/{0}".format(fname),
|
||||||
|
set_archiving=True,
|
||||||
|
initdb_params=['--data-checksums'],
|
||||||
|
pg_options={'wal_level': 'replica'}
|
||||||
|
)
|
||||||
|
|
||||||
|
node.start()
|
||||||
|
self.assertEqual(self.init_pb(node), six.b(""))
|
||||||
|
with node.connect("postgres") as con:
|
||||||
|
con.execute("CREATE TABLE tbl0005 (a text)")
|
||||||
|
con.commit()
|
||||||
|
|
||||||
|
backup_id = self.backup_pb(node)
|
||||||
|
|
||||||
|
# Corrupt WAL
|
||||||
wals_dir = os.path.join(self.backup_dir(node), "wal")
|
wals_dir = os.path.join(self.backup_dir(node), "wal")
|
||||||
wals = [f for f in os.listdir(wals_dir) if os.path.isfile(os.path.join(wals_dir, f)) and not f.endswith('.backup')]
|
wals = [f for f in os.listdir(wals_dir) if os.path.isfile(os.path.join(wals_dir, f)) and not f.endswith('.backup')]
|
||||||
wals.sort()
|
wals.sort()
|
||||||
@ -146,29 +123,60 @@ class ValidateTest(ProbackupTest, unittest.TestCase):
|
|||||||
f.write(six.b("blablabla"))
|
f.write(six.b("blablabla"))
|
||||||
f.close
|
f.close
|
||||||
|
|
||||||
try:
|
# Simple validate
|
||||||
self.validate_pb(node, id_backup, options=['--xid=%s' % target_xid])
|
|
||||||
# we should die here because exception is what we expect to happen
|
|
||||||
exit(1)
|
|
||||||
except ProbackupException, e:
|
|
||||||
self.assertEqual(
|
|
||||||
True,
|
|
||||||
'Possible WAL CORRUPTION' in e.message
|
|
||||||
)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.validate_pb(node)
|
self.validate_pb(node)
|
||||||
# we should die here because exception is what we expect to happen
|
self.assertEqual(1, 0, "Expecting Error because of wal corruption. THIS IS BAD")
|
||||||
exit(1)
|
|
||||||
except ProbackupException, e:
|
except ProbackupException, e:
|
||||||
self.assertEqual(
|
self.assertEqual(True, 'Possible WAL CORRUPTION' in e.message)
|
||||||
True,
|
|
||||||
'Possible WAL CORRUPTION' in e.message
|
self.assertEqual('CORRUPT', self.show_pb(node, id=backup_id)['status'], 'Backup STATUS should be "CORRUPT"')
|
||||||
)
|
|
||||||
|
|
||||||
node.stop()
|
node.stop()
|
||||||
|
|
||||||
# @unittest.skip("123")
|
def test_validate_broken_wal_2(self):
|
||||||
|
"""recovery to latest from full backup"""
|
||||||
|
fname = self.id().split('.')[3]
|
||||||
|
node = self.make_simple_node(base_dir="tmp_dirs/validate/{0}".format(fname),
|
||||||
|
set_archiving=True,
|
||||||
|
initdb_params=['--data-checksums'],
|
||||||
|
pg_options={'wal_level': 'replica'}
|
||||||
|
)
|
||||||
|
|
||||||
|
node.start()
|
||||||
|
self.assertEqual(self.init_pb(node), six.b(""))
|
||||||
|
with node.connect("postgres") as con:
|
||||||
|
con.execute("CREATE TABLE tbl0005 (a text)")
|
||||||
|
con.commit()
|
||||||
|
|
||||||
|
backup_id = self.backup_pb(node)
|
||||||
|
target_xid = None
|
||||||
|
with node.connect("postgres") as con:
|
||||||
|
res = con.execute("INSERT INTO tbl0005 VALUES ('inserted') RETURNING (xmin)")
|
||||||
|
con.commit()
|
||||||
|
target_xid = res[0][0]
|
||||||
|
node.execute("postgres", "SELECT pg_switch_xlog()")
|
||||||
|
|
||||||
|
# Corrupt WAL
|
||||||
|
wals_dir = os.path.join(self.backup_dir(node), "wal")
|
||||||
|
wals = [f for f in os.listdir(wals_dir) if os.path.isfile(os.path.join(wals_dir, f)) and not f.endswith('.backup')]
|
||||||
|
wals.sort()
|
||||||
|
for wal in wals:
|
||||||
|
f = open(os.path.join(wals_dir, wal), "rb+")
|
||||||
|
f.seek(256)
|
||||||
|
f.write(six.b("blablabla"))
|
||||||
|
f.close
|
||||||
|
|
||||||
|
# Simple validate
|
||||||
|
try:
|
||||||
|
self.validate_pb(node, backup_id, options=['--xid=%s' % target_xid])
|
||||||
|
self.assertEqual(1, 0, "Expecting Error because of wal corruption. THIS IS BAD")
|
||||||
|
except ProbackupException, e:
|
||||||
|
self.assertEqual(True, 'Possible WAL CORRUPTION' in e.message)
|
||||||
|
|
||||||
|
self.assertEqual('CORRUPT', self.show_pb(node, id=backup_id)['status'], 'Backup STATUS should be "CORRUPT"')
|
||||||
|
node.stop()
|
||||||
|
|
||||||
def test_validate_wal_lost_segment_1(self):
|
def test_validate_wal_lost_segment_1(self):
|
||||||
"""Loose segment which belong to some backup"""
|
"""Loose segment which belong to some backup"""
|
||||||
fname = self.id().split('.')[3]
|
fname = self.id().split('.')[3]
|
||||||
@ -188,25 +196,23 @@ class ValidateTest(ProbackupTest, unittest.TestCase):
|
|||||||
)
|
)
|
||||||
pgbench.wait()
|
pgbench.wait()
|
||||||
pgbench.stdout.close()
|
pgbench.stdout.close()
|
||||||
self.backup_pb(node, backup_type='full')
|
backup_id = self.backup_pb(node, backup_type='full')
|
||||||
|
|
||||||
|
# Delete wal segment
|
||||||
wals_dir = os.path.join(self.backup_dir(node), "wal")
|
wals_dir = os.path.join(self.backup_dir(node), "wal")
|
||||||
wals = [f for f in os.listdir(wals_dir) if os.path.isfile(os.path.join(wals_dir, f)) and not f.endswith('.backup')]
|
wals = [f for f in os.listdir(wals_dir) if os.path.isfile(os.path.join(wals_dir, f)) and not f.endswith('.backup')]
|
||||||
os.remove(os.path.join(self.backup_dir(node), "wal", wals[1]))
|
os.remove(os.path.join(self.backup_dir(node), "wal", wals[1]))
|
||||||
try:
|
try:
|
||||||
self.validate_pb(node)
|
self.validate_pb(node)
|
||||||
# we should die here because exception is what we expect to happen
|
self.assertEqual(1, 0, "Expecting Error because of wal segment disappearance")
|
||||||
exit(1)
|
|
||||||
except ProbackupException, e:
|
except ProbackupException, e:
|
||||||
self.assertEqual(
|
self.assertEqual(True, 'is absent' in e.message)
|
||||||
True,
|
|
||||||
'is absent' in e.message
|
self.assertEqual('CORRUPT', self.show_pb(node, id=backup_id)['status'], 'Backup STATUS should be "CORRUPT"')
|
||||||
)
|
|
||||||
node.stop()
|
node.stop()
|
||||||
|
|
||||||
# @unittest.skip("123")
|
|
||||||
def test_validate_wal_lost_segment_2(self):
|
def test_validate_wal_lost_segment_2(self):
|
||||||
"""Loose segment located between backups. Expect to fail """
|
"""Loose segment located between backups"""
|
||||||
fname = self.id().split('.')[3]
|
fname = self.id().split('.')[3]
|
||||||
node = self.make_simple_node(base_dir="tmp_dirs/validate/{0}".format(fname),
|
node = self.make_simple_node(base_dir="tmp_dirs/validate/{0}".format(fname),
|
||||||
set_archiving=True,
|
set_archiving=True,
|
||||||
@ -216,6 +222,9 @@ class ValidateTest(ProbackupTest, unittest.TestCase):
|
|||||||
|
|
||||||
node.start()
|
node.start()
|
||||||
self.assertEqual(self.init_pb(node), six.b(""))
|
self.assertEqual(self.init_pb(node), six.b(""))
|
||||||
|
self.backup_pb(node, backup_type='full')
|
||||||
|
|
||||||
|
# make some wals
|
||||||
node.pgbench_init(scale=2)
|
node.pgbench_init(scale=2)
|
||||||
pgbench = node.pgbench(
|
pgbench = node.pgbench(
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
@ -224,38 +233,17 @@ class ValidateTest(ProbackupTest, unittest.TestCase):
|
|||||||
)
|
)
|
||||||
pgbench.wait()
|
pgbench.wait()
|
||||||
pgbench.stdout.close()
|
pgbench.stdout.close()
|
||||||
self.backup_pb(node, backup_type='full')
|
|
||||||
|
|
||||||
# need to do that to find segment between(!) backups
|
|
||||||
node.psql("postgres", "CREATE TABLE t1(a int)")
|
|
||||||
node.psql("postgres", "SELECT pg_switch_xlog()")
|
|
||||||
node.psql("postgres", "CREATE TABLE t2(a int)")
|
|
||||||
node.psql("postgres", "SELECT pg_switch_xlog()")
|
|
||||||
|
|
||||||
|
# delete last wal segment
|
||||||
wals_dir = os.path.join(self.backup_dir(node), "wal")
|
wals_dir = os.path.join(self.backup_dir(node), "wal")
|
||||||
wals = [f for f in os.listdir(wals_dir) if os.path.isfile(os.path.join(wals_dir, f)) and not f.endswith('.backup')]
|
wals = [f for f in os.listdir(wals_dir) if os.path.isfile(os.path.join(wals_dir, f)) and not f.endswith('.backup')]
|
||||||
wals = map(int, wals)
|
wals = map(int, wals)
|
||||||
|
|
||||||
# delete last wal segment
|
|
||||||
#print os.path.join(self.backup_dir(node), "wal", '0000000' + str(max(wals)))
|
|
||||||
os.remove(os.path.join(self.backup_dir(node), "wal", '0000000' + str(max(wals))))
|
os.remove(os.path.join(self.backup_dir(node), "wal", '0000000' + str(max(wals))))
|
||||||
|
|
||||||
# Need more accurate error message about loosing wal segment between backups
|
# Need more accurate error message about loosing wal segment between backups
|
||||||
try:
|
try:
|
||||||
self.backup_pb(node, backup_type='page')
|
self.backup_pb(node, backup_type='page')
|
||||||
# we should die here because exception is what we expect to happen
|
self.assertEqual(1, 0, "Expecting Error in PAGE backup because of wal segment disappearance")
|
||||||
exit(1)
|
|
||||||
except ProbackupException, e:
|
except ProbackupException, e:
|
||||||
self.assertEqual(
|
self.assertEqual(True, 'could not read WAL record' in e.message)
|
||||||
True,
|
|
||||||
'could not read WAL record' in e.message
|
|
||||||
)
|
|
||||||
self.delete_pb(node, id=self.show_pb(node)[1]['ID'])
|
|
||||||
|
|
||||||
##### Hole Smokes, Batman! We just lost a wal segment and know nothing about it
|
|
||||||
##### We need archive-push ASAP
|
|
||||||
self.backup_pb(node, backup_type='full')
|
|
||||||
self.assertEqual(False, 'validation completed successfully' in self.validate_pb(node))
|
|
||||||
########
|
|
||||||
|
|
||||||
node.stop()
|
node.stop()
|
||||||
|
Loading…
Reference in New Issue
Block a user