pg_probackup
337 строк · 12.2 Кб
1import unittest
2import os
3from time import sleep
4
5from .helpers.ptrack_helpers import ProbackupTest, ProbackupException
6from datetime import datetime, timedelta
7import subprocess
8
9
10class FalsePositive(ProbackupTest, unittest.TestCase):
11
12# @unittest.skip("skip")
13@unittest.expectedFailure
14def test_validate_wal_lost_segment(self):
15"""
16Loose segment located between backups. ExpectedFailure. This is BUG
17"""
18node = self.make_simple_node(
19base_dir=os.path.join(self.module_name, self.fname, 'node'),
20set_replication=True,
21initdb_params=['--data-checksums'])
22
23backup_dir = os.path.join(self.tmp_path, self.module_name, self.fname, 'backup')
24self.init_pb(backup_dir)
25self.add_instance(backup_dir, 'node', node)
26self.set_archiving(backup_dir, 'node', node)
27node.slow_start()
28
29self.backup_node(backup_dir, 'node', node)
30
31# make some wals
32node.pgbench_init(scale=5)
33
34# delete last wal segment
35wals_dir = os.path.join(backup_dir, "wal", 'node')
36wals = [f for f in os.listdir(wals_dir) if os.path.isfile(
37os.path.join(wals_dir, f)) and not f.endswith('.backup')]
38wals = map(int, wals)
39os.remove(os.path.join(wals_dir, '0000000' + str(max(wals))))
40
41# We just lost a wal segment and know nothing about it
42self.backup_node(backup_dir, 'node', node)
43self.assertTrue(
44'validation completed successfully' in self.validate_pb(
45backup_dir, 'node'))
46########
47
48@unittest.expectedFailure
49# Need to force validation of ancestor-chain
50def test_incremental_backup_corrupt_full_1(self):
51"""page-level backup with corrupted full backup"""
52node = self.make_simple_node(
53base_dir=os.path.join(self.module_name, self.fname, 'node'),
54initdb_params=['--data-checksums'])
55
56backup_dir = os.path.join(self.tmp_path, self.module_name, self.fname, 'backup')
57self.init_pb(backup_dir)
58self.add_instance(backup_dir, 'node', node)
59self.set_archiving(backup_dir, 'node', node)
60node.slow_start()
61
62backup_id = self.backup_node(backup_dir, 'node', node)
63file = os.path.join(
64backup_dir, "backups", "node",
65backup_id.decode("utf-8"), "database", "postgresql.conf")
66os.remove(file)
67
68try:
69self.backup_node(backup_dir, 'node', node, backup_type="page")
70# we should die here because exception is what we expect to happen
71self.assertEqual(
721, 0,
73"Expecting Error because page backup should not be "
74"possible without valid full backup.\n "
75"Output: {0} \n CMD: {1}".format(
76repr(self.output), self.cmd))
77except ProbackupException as e:
78self.assertEqual(
79e.message,
80'ERROR: Valid full backup on current timeline is not found. '
81'Create new FULL backup before an incremental one.\n',
82'\n Unexpected Error Message: {0}\n CMD: {1}'.format(
83repr(e.message), self.cmd))
84self.assertFalse(
85True,
86"Expecting Error because page backup should not be "
87"possible without valid full backup.\n "
88"Output: {0} \n CMD: {1}".format(
89repr(self.output), self.cmd))
90except ProbackupException as e:
91self.assertEqual(
92e.message,
93'ERROR: Valid full backup on current timeline is not found. '
94'Create new FULL backup before an incremental one.\n',
95'\n Unexpected Error Message: {0}\n CMD: {1}'.format(
96repr(e.message), self.cmd))
97
98self.assertEqual(
99self.show_pb(backup_dir, 'node')[0]['Status'], "ERROR")
100
101# @unittest.skip("skip")
102@unittest.expectedFailure
103def test_pg_10_waldir(self):
104"""
105test group access for PG >= 11
106"""
107if self.pg_config_version < self.version_to_num('10.0'):
108self.skipTest('You need PostgreSQL >= 10 for this test')
109
110wal_dir = os.path.join(
111os.path.join(self.tmp_path, self.module_name, self.fname), 'wal_dir')
112import shutil
113shutil.rmtree(wal_dir, ignore_errors=True)
114node = self.make_simple_node(
115base_dir=os.path.join(self.module_name, self.fname, 'node'),
116set_replication=True,
117initdb_params=[
118'--data-checksums',
119'--waldir={0}'.format(wal_dir)])
120
121backup_dir = os.path.join(self.tmp_path, self.module_name, self.fname, 'backup')
122self.init_pb(backup_dir)
123self.add_instance(backup_dir, 'node', node)
124node.slow_start()
125
126# take FULL backup
127self.backup_node(
128backup_dir, 'node', node, options=['--stream'])
129
130pgdata = self.pgdata_content(node.data_dir)
131
132# restore backup
133node_restored = self.make_simple_node(
134base_dir=os.path.join(self.module_name, self.fname, 'node_restored'))
135node_restored.cleanup()
136
137self.restore_node(
138backup_dir, 'node', node_restored)
139
140# compare pgdata permissions
141pgdata_restored = self.pgdata_content(node_restored.data_dir)
142self.compare_pgdata(pgdata, pgdata_restored)
143
144self.assertTrue(
145os.path.islink(os.path.join(node_restored.data_dir, 'pg_wal')),
146'pg_wal should be symlink')
147
148@unittest.expectedFailure
149# @unittest.skip("skip")
150def test_recovery_target_time_backup_victim(self):
151"""
152Check that for validation to recovery target
153probackup chooses valid backup
154https://github.com/postgrespro/pg_probackup/issues/104
155"""
156backup_dir = os.path.join(self.tmp_path, self.module_name, self.fname, 'backup')
157node = self.make_simple_node(
158base_dir=os.path.join(self.module_name, self.fname, 'node'),
159set_replication=True,
160initdb_params=['--data-checksums'])
161
162self.init_pb(backup_dir)
163self.add_instance(backup_dir, 'node', node)
164self.set_archiving(backup_dir, 'node', node)
165node.slow_start()
166
167# FULL backup
168self.backup_node(backup_dir, 'node', node)
169
170node.safe_psql(
171"postgres",
172"create table t_heap as select 1 as id, md5(i::text) as text, "
173"md5(repeat(i::text,10))::tsvector as tsvector "
174"from generate_series(0,10000) i")
175
176target_time = node.safe_psql(
177"postgres",
178"select now()").rstrip()
179
180node.safe_psql(
181"postgres",
182"create table t_heap1 as select 1 as id, md5(i::text) as text, "
183"md5(repeat(i::text,10))::tsvector as tsvector "
184"from generate_series(0,100) i")
185
186gdb = self.backup_node(backup_dir, 'node', node, gdb=True)
187
188# Attention! This breakpoint is set to a probackup internal fuction, not a postgres core one
189gdb.set_breakpoint('pg_stop_backup')
190gdb.run_until_break()
191gdb.remove_all_breakpoints()
192gdb._execute('signal SIGINT')
193gdb.continue_execution_until_error()
194
195backup_id = self.show_pb(backup_dir, 'node')[1]['id']
196
197self.assertEqual(
198'ERROR',
199self.show_pb(backup_dir, 'node', backup_id)['status'],
200'Backup STATUS should be "ERROR"')
201
202self.validate_pb(
203backup_dir, 'node',
204options=['--recovery-target-time={0}'.format(target_time)])
205
206@unittest.expectedFailure
207# @unittest.skip("skip")
208def test_recovery_target_lsn_backup_victim(self):
209"""
210Check that for validation to recovery target
211probackup chooses valid backup
212https://github.com/postgrespro/pg_probackup/issues/104
213"""
214backup_dir = os.path.join(self.tmp_path, self.module_name, self.fname, 'backup')
215node = self.make_simple_node(
216base_dir=os.path.join(self.module_name, self.fname, 'node'),
217set_replication=True,
218initdb_params=['--data-checksums'])
219
220self.init_pb(backup_dir)
221self.add_instance(backup_dir, 'node', node)
222self.set_archiving(backup_dir, 'node', node)
223node.slow_start()
224
225# FULL backup
226self.backup_node(backup_dir, 'node', node)
227
228node.safe_psql(
229"postgres",
230"create table t_heap as select 1 as id, md5(i::text) as text, "
231"md5(repeat(i::text,10))::tsvector as tsvector "
232"from generate_series(0,10000) i")
233
234node.safe_psql(
235"postgres",
236"create table t_heap1 as select 1 as id, md5(i::text) as text, "
237"md5(repeat(i::text,10))::tsvector as tsvector "
238"from generate_series(0,100) i")
239
240gdb = self.backup_node(
241backup_dir, 'node', node,
242options=['--log-level-console=LOG'], gdb=True)
243
244# Attention! This breakpoint is set to a probackup internal fuction, not a postgres core one
245gdb.set_breakpoint('pg_stop_backup')
246gdb.run_until_break()
247gdb.remove_all_breakpoints()
248gdb._execute('signal SIGINT')
249gdb.continue_execution_until_error()
250
251backup_id = self.show_pb(backup_dir, 'node')[1]['id']
252
253self.assertEqual(
254'ERROR',
255self.show_pb(backup_dir, 'node', backup_id)['status'],
256'Backup STATUS should be "ERROR"')
257
258self.switch_wal_segment(node)
259
260target_lsn = self.show_pb(backup_dir, 'node', backup_id)['start-lsn']
261
262self.validate_pb(
263backup_dir, 'node',
264options=['--recovery-target-lsn={0}'.format(target_lsn)])
265
266# @unittest.skip("skip")
267@unittest.expectedFailure
268def test_streaming_timeout(self):
269"""
270Illustrate the problem of loosing exact error
271message because our WAL streaming engine is "borrowed"
272from pg_receivexlog
273"""
274backup_dir = os.path.join(self.tmp_path, self.module_name, self.fname, 'backup')
275node = self.make_simple_node(
276base_dir=os.path.join(self.module_name, self.fname, 'node'),
277set_replication=True,
278initdb_params=['--data-checksums'],
279pg_options={
280'checkpoint_timeout': '1h',
281'wal_sender_timeout': '5s'})
282
283self.init_pb(backup_dir)
284self.add_instance(backup_dir, 'node', node)
285node.slow_start()
286
287# FULL backup
288gdb = self.backup_node(
289backup_dir, 'node', node, gdb=True,
290options=['--stream', '--log-level-file=LOG'])
291
292# Attention! This breakpoint is set to a probackup internal fuction, not a postgres core one
293gdb.set_breakpoint('pg_stop_backup')
294gdb.run_until_break()
295
296sleep(10)
297gdb.continue_execution_until_error()
298gdb._execute('detach')
299sleep(2)
300
301log_file_path = os.path.join(backup_dir, 'log', 'pg_probackup.log')
302with open(log_file_path) as f:
303log_content = f.read()
304
305self.assertIn(
306'could not receive data from WAL stream',
307log_content)
308
309self.assertIn(
310'ERROR: Problem in receivexlog',
311log_content)
312
313# @unittest.skip("skip")
314@unittest.expectedFailure
315def test_validate_all_empty_catalog(self):
316"""
317"""
318node = self.make_simple_node(
319base_dir=os.path.join(self.module_name, self.fname, 'node'),
320initdb_params=['--data-checksums'])
321
322backup_dir = os.path.join(self.tmp_path, self.module_name, self.fname, 'backup')
323self.init_pb(backup_dir)
324
325try:
326self.validate_pb(backup_dir)
327self.assertEqual(
3281, 0,
329"Expecting Error because backup_dir is empty.\n "
330"Output: {0} \n CMD: {1}".format(
331repr(self.output), self.cmd))
332except ProbackupException as e:
333self.assertIn(
334'ERROR: This backup catalog contains no backup instances',
335e.message,
336'\n Unexpected Error Message: {0}\n CMD: {1}'.format(
337repr(e.message), self.cmd))
338