Skip to content

Commit 3c82429

Browse files
committed
Add delete and backup tests. Add simple parser for show line.
1 parent e7d6a08 commit 3c82429

File tree

5 files changed

+262
-14
lines changed

5 files changed

+262
-14
lines changed

tests/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import unittest
22

3-
from . import init_test, option_test, show_test
3+
from . import init_test, option_test, show_test, backup_test, delete_test
44

55

66
def load_tests(loader, tests, pattern):
77
suite = unittest.TestSuite()
88
suite.addTests(loader.loadTestsFromModule(init_test))
99
suite.addTests(loader.loadTestsFromModule(option_test))
1010
suite.addTests(loader.loadTestsFromModule(show_test))
11+
suite.addTests(loader.loadTestsFromModule(backup_test))
12+
suite.addTests(loader.loadTestsFromModule(delete_test))
1113

1214
return suite

tests/backup_test.py

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import unittest
2+
from os import path
3+
import six
4+
from .pb_lib import ProbackupTest
5+
from testgres import stop_all
6+
7+
8+
class BackupTest(ProbackupTest, unittest.TestCase):
9+
10+
def __init__(self, *args, **kwargs):
11+
super(BackupTest, self).__init__(*args, **kwargs)
12+
13+
@classmethod
14+
def tearDownClass(cls):
15+
stop_all()
16+
17+
def test_backup_modes_1(self):
18+
"""standart backup modes"""
19+
node = self.make_bnode('backup_modes_', base_dir="tmp_dirs/backup/backup_modes_1")
20+
node.start()
21+
self.assertEqual(self.init_pb(node), six.b(""))
22+
23+
# detect ptrack
24+
is_ptrack = node.execute("postgres", "SELECT proname FROM pg_proc WHERE proname='pg_ptrack_clear'")
25+
if len(is_ptrack):
26+
node.append_conf("postgresql.conf", "ptrack_enable = on")
27+
node.restart()
28+
29+
# full backup mode
30+
with open(path.join(node.logs_dir, "backup_full.log"), "wb") as backup_log:
31+
backup_log.write(self.backup_pb(node, options=["--verbose"]))
32+
33+
show_backup = self.show_pb(node)[0]
34+
self.assertEqual(show_backup.status, six.b("OK"))
35+
self.assertEqual(show_backup.mode, six.b("FULL"))
36+
37+
# page backup mode
38+
with open(path.join(node.logs_dir, "backup_page.log"), "wb") as backup_log:
39+
backup_log.write(self.backup_pb(node, backup_type="page", options=["--verbose"]))
40+
41+
show_backup = self.show_pb(node)[0]
42+
self.assertEqual(show_backup.status, six.b("OK"))
43+
self.assertEqual(show_backup.mode, six.b("PAGE"))
44+
45+
# ptrack backup mode
46+
if len(is_ptrack):
47+
with open(path.join(node.logs_dir, "backup_ptrack.log"), "wb") as backup_log:
48+
backup_log.write(self.backup_pb(node, backup_type="ptrack", options=["--verbose"]))
49+
50+
show_backup = self.show_pb(node)[0]
51+
self.assertEqual(show_backup.status, six.b("OK"))
52+
self.assertEqual(show_backup.mode, six.b("PTRACK"))
53+
54+
node.stop()
55+
56+
def test_smooth_checkpoint_2(self):
57+
"""full backup with smooth checkpoint"""
58+
node = self.make_bnode('smooth_checkpoint_2', base_dir="tmp_dirs/backup/smooth_checkpoint_2")
59+
node.start()
60+
self.assertEqual(self.init_pb(node), six.b(""))
61+
62+
with open(path.join(node.logs_dir, "backup.log"), "wb") as backup_log:
63+
backup_log.write(self.backup_pb(node, options=["--verbose", "-C"]))
64+
65+
self.assertEqual(self.show_pb(node)[0].status, six.b("OK"))
66+
67+
node.stop()
68+
69+
def test_page_backup_without_full_3(self):
70+
"""page-level backup without validated full backup"""
71+
node = self.make_bnode('without_full_3', base_dir="tmp_dirs/backup/without_full_3")
72+
node.start()
73+
self.assertEqual(self.init_pb(node), six.b(""))
74+
75+
with open(path.join(node.logs_dir, "backup.log"), "wb") as backup_log:
76+
backup_log.write(self.backup_pb(node, backup_type="page", options=["--verbose"]))
77+
78+
self.assertEqual(self.show_pb(node)[0].status, six.b("ERROR"))
79+
80+
node.stop()
81+
82+
def test_ptrack_threads_4(self):
83+
"""ptrack multi thread backup mode"""
84+
node = self.make_bnode(
85+
'ptrack_threads_4',
86+
base_dir="tmp_dirs/backup/ptrack_threads_4",
87+
options={"ptrack_enable": "on"}
88+
)
89+
node.start()
90+
self.assertEqual(self.init_pb(node), six.b(""))
91+
92+
with open(path.join(node.logs_dir, "backup_full.log"), "wb") as backup_log:
93+
backup_log.write(self.backup_pb(node, backup_type="full", options=["--verbose", "-j", "4"]))
94+
95+
self.assertEqual(self.show_pb(node)[0].status, six.b("OK"))
96+
97+
with open(path.join(node.logs_dir, "backup_ptrack.log"), "wb") as backup_log:
98+
backup_log.write(self.backup_pb(node, backup_type="ptrack", options=["--verbose", "-j", "4"]))
99+
100+
self.assertEqual(self.show_pb(node)[0].status, six.b("OK"))
101+
102+
node.stop()
103+
104+
def test_ptrack_threads_stream_5(self):
105+
"""ptrack multi thread backup mode and stream"""
106+
node = self.make_bnode(
107+
'ptrack_threads_stream_5',
108+
base_dir="tmp_dirs/backup/ptrack_threads_stream_5",
109+
options={
110+
"ptrack_enable": "on",
111+
"max_wal_senders": "5"
112+
}
113+
)
114+
node.append_conf("pg_hba.conf", "local replication all trust")
115+
node.append_conf("pg_hba.conf", "host replication all 127.0.0.1/32 trust")
116+
node.start()
117+
self.assertEqual(self.init_pb(node), six.b(""))
118+
119+
with open(path.join(node.logs_dir, "backup_full.log"), "wb") as backup_log:
120+
backup_log.write(self.backup_pb(
121+
node,
122+
backup_type="full",
123+
options=["--verbose", "-j", "4", "--stream"]
124+
))
125+
126+
self.assertEqual(self.show_pb(node)[0].status, six.b("OK"))
127+
128+
with open(path.join(node.logs_dir, "backup_ptrack.log"), "wb") as backup_log:
129+
backup_log.write(self.backup_pb(
130+
node,
131+
backup_type="ptrack",
132+
options=["--verbose", "-j", "4", "--stream"]
133+
))
134+
135+
self.assertEqual(self.show_pb(node)[0].status, six.b("OK"))
136+
137+
node.stop()

tests/delete_test.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import unittest
2+
from os import path
3+
import six
4+
from .pb_lib import ProbackupTest
5+
from testgres import stop_all
6+
import subprocess
7+
8+
9+
class DeleteTest(ProbackupTest, unittest.TestCase):
10+
11+
def __init__(self, *args, **kwargs):
12+
super(DeleteTest, self).__init__(*args, **kwargs)
13+
14+
@classmethod
15+
def tearDownClass(cls):
16+
stop_all()
17+
18+
def test_delete_full_backups_1(self):
19+
"""delete full backups"""
20+
node = self.make_bnode('delete_full_backups_1', base_dir="tmp_dirs/delete/delete_full_backups_1")
21+
node.start()
22+
self.assertEqual(self.init_pb(node), six.b(""))
23+
node.pgbench_init()
24+
25+
# full backup mode
26+
with open(path.join(node.logs_dir, "backup_1.log"), "wb") as backup_log:
27+
backup_log.write(self.backup_pb(node, options=["--verbose"]))
28+
29+
pgbench = node.pgbench(stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
30+
pgbench.wait()
31+
pgbench.stdout.close()
32+
33+
with open(path.join(node.logs_dir, "backup_2.log"), "wb") as backup_log:
34+
backup_log.write(self.backup_pb(node, options=["--verbose"]))
35+
36+
pgbench = node.pgbench(stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
37+
pgbench.wait()
38+
pgbench.stdout.close()
39+
40+
with open(path.join(node.logs_dir, "backup_3.log"), "wb") as backup_log:
41+
backup_log.write(self.backup_pb(node, options=["--verbose"]))
42+
43+
show_backups = self.show_pb(node)
44+
id_1 = show_backups[0].id
45+
id_2 = show_backups[2].id
46+
self.delete_pb(node, show_backups[1].id)
47+
show_backups = self.show_pb(node)
48+
self.assertEqual(show_backups[0].id, id_1)
49+
self.assertEqual(show_backups[1].id, id_2)
50+
51+
node.stop()
52+
53+
def test_delete_increment_2(self):
54+
"""delete increment and all after him"""
55+
node = self.make_bnode('delete_increment_2', base_dir="tmp_dirs/delete/delete_increment_2")
56+
node.start()
57+
self.assertEqual(self.init_pb(node), six.b(""))
58+
59+
# full backup mode
60+
with open(path.join(node.logs_dir, "backup_1.log"), "wb") as backup_log:
61+
backup_log.write(self.backup_pb(node, options=["--verbose"]))
62+
63+
# page backup mode
64+
with open(path.join(node.logs_dir, "backup_2.log"), "wb") as backup_log:
65+
backup_log.write(self.backup_pb(node, backup_type="page", options=["--verbose"]))
66+
67+
# page backup mode
68+
with open(path.join(node.logs_dir, "backup_3.log"), "wb") as backup_log:
69+
backup_log.write(self.backup_pb(node, backup_type="page", options=["--verbose"]))
70+
71+
show_backups = self.show_pb(node)
72+
self.assertEqual(len(show_backups), 3)
73+
self.delete_pb(node, show_backups[1].id)
74+
show_backups = self.show_pb(node)
75+
self.assertEqual(len(show_backups), 1)
76+
self.assertEqual(show_backups[0].mode, six.b("FULL"))
77+
self.assertEqual(show_backups[0].status, six.b("OK"))
78+
79+
node.stop()

tests/pb_lib.py

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,21 @@ def dir_files(base_dir):
1717
return out_list
1818

1919

20+
class ShowBackup(object):
21+
def __init__(self, split_line):
22+
self.id = split_line[0]
23+
# TODO: parse to datetime
24+
self.recovery_time = "%s %s" % (split_line[1], split_line[2])
25+
self.mode = split_line[3]
26+
self.cur_tli = split_line[4]
27+
self.parent_tli = split_line[6]
28+
# TODO: parse to interval
29+
self.time = split_line[7]
30+
# TODO: maybe rename to size?
31+
self.data = split_line[8]
32+
self.status = split_line[9]
33+
34+
2035
class ProbackupTest(object):
2136
def __init__(self, *args, **kwargs):
2237
super(ProbackupTest, self).__init__(*args, **kwargs)
@@ -36,13 +51,10 @@ def arcwal_dir(self, node):
3651
def backup_dir(self, node):
3752
return os.path.abspath("%s/backup" % node.base_dir)
3853

39-
def make_bnode(self, name, base_dir=None):
40-
node = get_new_node('test', base_dir=path.join(self.dir_path, base_dir))
41-
try:
42-
node.cleanup()
43-
except:
44-
pass
45-
shutil.rmtree(self.backup_dir(node), ignore_errors=True)
54+
def make_bnode(self, name, base_dir=None, options={}):
55+
real_base_dir = path.join(self.dir_path, base_dir)
56+
shutil.rmtree(real_base_dir, ignore_errors=True)
57+
node = get_new_node('test', base_dir=real_base_dir)
4658
node.init()
4759

4860
node.append_conf("postgresql.conf", "wal_level = hot_standby")
@@ -51,6 +63,10 @@ def make_bnode(self, name, base_dir=None):
5163
"postgresql.conf",
5264
"""archive_command = 'cp "%%p" "%s/%%f"'""" % os.path.abspath(self.arcwal_dir(node))
5365
)
66+
67+
for key, value in six.iteritems(options):
68+
node.append_conf("postgresql.conf", "%s = %s" % (key, value))
69+
5470
return node
5571

5672
def run_pb(self, command):
@@ -86,7 +102,7 @@ def backup_pb(self, node, backup_type="full", options=[]):
86102
# print(cmd_list)
87103
return self.run_pb(cmd_list + options)
88104

89-
def show_pb(self, node, id=None, options=[]):
105+
def show_pb(self, node, id=None, options=[], as_text=False):
90106
cmd_list = [
91107
"-B", self.backup_dir(node),
92108
"show",
@@ -95,9 +111,12 @@ def show_pb(self, node, id=None, options=[]):
95111
cmd_list += [id]
96112

97113
# print(cmd_list)
98-
return self.run_pb(options + cmd_list)
114+
if as_text:
115+
return self.run_pb(options + cmd_list)
116+
else:
117+
return [ShowBackup(line.split()) for line in self.run_pb(options + cmd_list).splitlines()[3:]]
99118

100-
def validate_pb(self, node, id=None, options=[]):
119+
def validate_pb(self, node, id, options=[]):
101120
cmd_list = [
102121
"-B", self.backup_dir(node),
103122
"validate",
@@ -107,3 +126,14 @@ def validate_pb(self, node, id=None, options=[]):
107126

108127
# print(cmd_list)
109128
return self.run_pb(options + cmd_list)
129+
130+
def delete_pb(self, node, id=None, options=[]):
131+
cmd_list = [
132+
"-B", self.backup_dir(node),
133+
"delete",
134+
]
135+
if id:
136+
cmd_list += [id]
137+
138+
# print(cmd_list)
139+
return self.run_pb(options + cmd_list)

tests/show_test.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def test_ok_1(self):
2525
self.backup_pb(node, options=["--quiet"]),
2626
six.b("")
2727
)
28-
self.assertIn(six.b("OK"), self.show_pb(node))
28+
self.assertIn(six.b("OK"), self.show_pb(node, as_text=True))
2929

3030
node.stop()
3131

@@ -40,10 +40,10 @@ def test_corrupt_2(self):
4040
six.b("")
4141
)
4242

43-
id_backup = self.show_pb(node).splitlines()[3].split()[0]
43+
id_backup = self.show_pb(node)[0].id
4444
os.remove(path.join(self.backup_dir(node), "backups", id_backup.decode("utf-8"), "database", "postgresql.conf"))
4545

4646
self.validate_pb(node, id_backup)
47-
self.assertIn(six.b("CORRUPT"), self.show_pb(node))
47+
self.assertIn(six.b("CORRUPT"), self.show_pb(node, as_text=True))
4848

4949
node.stop()

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy