diff --git a/tests/bugs/gh_7186_test.py b/tests/bugs/gh_7186_test.py new file mode 100644 index 00000000..0676010c --- /dev/null +++ b/tests/bugs/gh_7186_test.py @@ -0,0 +1,107 @@ +#coding:utf-8 + +""" +ID: issue-7186 +ISSUE: https://github.com/FirebirdSQL/firebird/issues/7186 +TITLE: Nbackup RDB$BACKUP_HISTORY cleanup +DESCRIPTION: + Test verifies ability to specify command switches '-clean_history' and 'keep N rows' in NBACKUP utility. + Temporary user and role are created. System privilege USE_NBACKUP_UTILITY is granted to role, and role is granted to this user. + All executions of NBACKUP are performed as this temporary user. + + Several levels of incremental backups are created WITHOUT this command switches (see 'NBK_COUNT_BEFORE_CLEANUP'). + Then we run nbackup times with switch '-clean_hist' and require to keep rows. + Finally, we check content of RDB$BACKUP_HISTORY table: only NBK_KEEP_ROWS records must be selected from it. + + ::: NB ::: + It seems that currently firebird-driver does not support Services API parameters related to cleanup history + (isc_spb_nbk_clean_history; isc_spb_nbk_keep_days and isc_spb_nbk_keep_rows ). + Test will be modified after introducing this supoport. + + Checked on 5.0.0.967 SS/CS, 4.0.3.2904 SS/CS -- all fine. +""" + +import pytest +from firebird.qa import * +from typing import List +from pathlib import Path +import subprocess +import re +import locale +import time + + +db = db_factory() + +act = python_act('db') + +NBK_COUNT_BEFORE_CLEANUP = 6 +tmp_nbk_files_before_cleanup = temp_files( [ f'tmp_7186.nbk{i}' for i in range(NBK_COUNT_BEFORE_CLEANUP) ] ) + +NBK_COUNT_WITH_CLEANUP = 4 +tmp_nbk_files_with_cleanup = temp_files( [ f'tmp_7186.nbk{i}' for i in range(NBK_COUNT_BEFORE_CLEANUP, NBK_COUNT_BEFORE_CLEANUP + NBK_COUNT_WITH_CLEANUP) ] ) + +NBK_KEEP_ROWS = 3 + +tmp_user = user_factory('db', name='gh_7186_user', password = '123') +tmp_role = role_factory('db', name='gh_7186_role') + +expected_stdout = """ +""" + +@pytest.mark.version('>=4.0.3') +def test_1(act: Action, tmp_nbk_files_before_cleanup: List[Path], tmp_nbk_files_with_cleanup: List[Path], tmp_user: User, tmp_role: Role, capsys): + init_sql = f""" + recreate table test(id int generated always as identity (start with 0)); + grant insert,select on test to public; + alter role {tmp_role.name} set system privileges to USE_NBACKUP_UTILITY; + grant default {tmp_role.name} to user {tmp_user.name}; + commit; + """ + act.expected_stdout = '' + act.isql(switches=[], input = init_sql, combine_output=True) + assert act.clean_stdout == act.clean_expected_stdout + act.reset() + + with act.db.connect() as con: + for i,tmp_nbk_i in enumerate(tmp_nbk_files_before_cleanup): + con.execute_immediate('insert into test default values') + con.commit() + act.expected_stderr = '' + act.nbackup(switches=['-user', tmp_user.name, '-pas', tmp_user.password, '-b', str(i), act.db.dsn, tmp_nbk_i], credentials = False, io_enc = locale.getpreferredencoding()) + assert act.clean_stderr == act.clean_expected_stderr + act.reset() + + + # Now we try to cleanup history of nbackups, using only ROWS: + # act.nbackup(switches=['-user', tmp_user.name, '-pas', tmp_user.password, '-b', str(i), act.db.dsn, tmp_nbk_i], combine_output = True, credentials = False, io_enc = locale.getpreferredencoding()) + # nbackup -B 10 C:\temp\pytest-of-PashaZ\pytest-110\test_10\TEST.FDB C:\temp\pytest-of-PashaZ\pytest-110\test_10\tmp_7186.nbk10 -clean_hist -keep 3 row + + for i,tmp_nbk_i in enumerate(tmp_nbk_files_with_cleanup): + act.expected_stderr = '' + act.nbackup(switches=['-user', tmp_user.name, '-pas', tmp_user.password, '-b', str(NBK_COUNT_BEFORE_CLEANUP + i), act.db.dsn, tmp_nbk_i, '-clean_hist', '-keep', str(NBK_KEEP_ROWS), 'row'], credentials = False, io_enc = locale.getpreferredencoding()) + assert act.clean_stderr == act.clean_expected_stderr + act.reset() + + test_sql = """ + set list on; + set count on; + select rdb$backup_id, rdb$backup_level + from rdb$backup_history + order by rdb$backup_id; + """ + act.expected_stdout = f""" + RDB$BACKUP_ID {NBK_COUNT_BEFORE_CLEANUP + NBK_COUNT_WITH_CLEANUP - 2} + RDB$BACKUP_LEVEL {NBK_COUNT_BEFORE_CLEANUP + NBK_COUNT_WITH_CLEANUP - 3} + + RDB$BACKUP_ID {NBK_COUNT_BEFORE_CLEANUP + NBK_COUNT_WITH_CLEANUP - 1} + RDB$BACKUP_LEVEL {NBK_COUNT_BEFORE_CLEANUP + NBK_COUNT_WITH_CLEANUP - 2} + + RDB$BACKUP_ID {NBK_COUNT_BEFORE_CLEANUP + NBK_COUNT_WITH_CLEANUP - 0} + RDB$BACKUP_LEVEL {NBK_COUNT_BEFORE_CLEANUP + NBK_COUNT_WITH_CLEANUP - 1} + + Records affected: {NBK_KEEP_ROWS} + """ + act.isql(switches=[], input = test_sql, combine_output=True) + assert act.clean_stdout == act.clean_expected_stdout + act.reset()