diff --git a/tests/bugs/core_6392_test.py b/tests/bugs/core_6392_test.py index c6046d91..2f38e333 100644 --- a/tests/bugs/core_6392_test.py +++ b/tests/bugs/core_6392_test.py @@ -5,224 +5,125 @@ ID: issue-6630 ISSUE: 6630 TITLE: Space in database path prevent working gbak -se ... -b "pat to/database" backup DESCRIPTION: - Test creates windows BATCH file for main job: - * create folder with spaces and some non-alphabetic characters (use "[", "]", "(", ")" etc); - * create .sql script which will make database with spaces and non-alphabetic characters in this folder; - * try to backup and restore using "simple" gbak commend (i.e. without "-se" command switch); - * try to backup and restore using "-se" command switch; - * try to backup and restore using services manager. - Batch output is redirected to log and then we parse this log with expectation to find there messages - which prove successful results for each action. - - Confirmed bug on 4.0.0.2173. - Checked on 3.0.7.33358; 4.0.0.2180 SS/SC/CS: all fine. - - ::: NOTE ::: - Some problem still exists when DB file or folder has name which last character is '.' or ' ' (dot or space). - Database will be created but attempt to backup raises: "gbak: ERROR:cannot open backup file ..." JIRA: CORE-6392 FBTEST: bugs.core_6392 +NOTES: + [24.07.2022] pzotov + Reproduced problem on 4.0.0.2173. + gbak: ERROR:multiple sources or destinations specified + gbak: ERROR: Exiting before completion due to errors + gbak:Exiting before completion due to errors + ::: NOTE ::: + Problem exists when DB file or folder has trailing character = '.' or ' ' (dot or space). + Test does not use such case. + Checked on 3.0.8.33535, 4.0.1.2692, 5.0.0.591 """ +import shutil +import re +import subprocess +from pathlib import Path import pytest from firebird.qa import * +import time db = db_factory() +bkp_log = temp_file('backup_log.tmp') +res_log = temp_file('restore_log.tmp') + act = python_act('db', substitutions=[('[\t ]+', ' ')]) -expected_stdout = """ - CHECK POINT. Trying to create database. - CHECK POINT. Result: SUCCESS. +expected_backup_out = 'Backup completed OK.' +expected_restore_out = 'Restore completed OK.' - CHECK POINT. Trying to BACKUP without "-se" switch. - closing file, committing, and finishing - - CHECK POINT. Trying to restore without "-se". - finishing, closing, and going home - - CHECK POINT. Trying to backup using gbak WITH "-se" switch. - closing file, committing, and finishing - - CHECK POINT. Trying to restore using gbak WITH "-se" switch. - finishing, closing, and going home - - CHECK POINT. Trying to backup using fbsvcmgr. - closing file, committing, and finishing - - CHECK POINT. Trying to restore using fbsvcmgr. - finishing, closing, and going home -""" - -@pytest.mark.skip('FIXME: Not IMPLEMENTED') @pytest.mark.version('>=3.0.7') @pytest.mark.platform('Windows') -def test_1(act: Action): - pytest.fail("Not IMPLEMENTED") +# gbak: ERROR:cannot open status and error output file .temp_file_fixture at 0x0000024389962040> +# gbak:Exiting before completion due to errors +def test_1(act: Action, bkp_log: Path, res_log: Path, capsys): + p_base = Path(act.db.db_path).parent + p_work = p_base / "..str@nge (path; folder & name)," + Path(p_work).mkdir(parents=True, exist_ok=False) -# test_script_1 -#--- -# -# import os -# import sys -# import time -# import subprocess -# import re -# from fdb import services -# -# os.environ["ISC_USER"] = user_name -# os.environ["ISC_PASSWORD"] = user_password -# -# #--------------------------------------------- -# -# def flush_and_close(file_handle): -# # https://docs.python.org/2/library/os.html#os.fsync -# # If you're starting with a Python file object f, -# # first do f.flush(), and -# # then do os.fsync(f.fileno()), to ensure that all internal buffers associated with f are written to disk. -# global os -# -# file_handle.flush() -# if file_handle.mode not in ('r', 'rb'): -# # otherwise: "OSError: [Errno 9] Bad file descriptor"! -# os.fsync(file_handle.fileno()) -# file_handle.close() -# -# #-------------------------------------------- -# -# def cleanup( f_names_list ): -# global os -# for i in range(len( f_names_list )): -# if os.path.isfile( f_names_list[i]): -# os.remove( f_names_list[i] ) -# #-------------------------------------------- -# -# fb_home = os.path.split( services.connect(host='localhost', user= user_name, password= user_password).get_home_directory() )[0] -# db_conn.close() -# -# # tmpdir='c:\\\\temp\\\\folder with spaces ' -# # gbak: ERROR:cannot open backup file c: emp -# older with spaces \\db with spaces. . .fbk -# -# # tmpdir='c:\\\\temp\\\\folder with spaces..' -# # gbak: ERROR:cannot open backup file c: emp -# older with spaces..\\db with spaces. . .fbk -# -# #tmpdir='c:\\\\temp\\\\^!very strange^! folder with (many) spaces; created temporary, only for core-6392^! ' -# -# #dbname='(strange name^!) DB with #lot# of excessive spaces; created temporary, only for core-6392^!. . .fdb' -# # gbak: ERROR:cannot open backup file // but database is created OK. -# -# #dbname='(strange name^!) DB with #lot# of excessive spaces, created temporary, only for core-6392^!. . .fdb' -# # gbak: ERROR:cannot open backup file // but database is created OK. -# -# tmpdir='c:\\\\temp\\\\ [[[ strange ]]] folder with {{{ lot of }}} spaces^!' -# dbname='DB with very^! ))) strange ((( name; created for core-6392.fdb' -# -# bkname=( '.'.join( dbname.split('.')[:-1] )+'.fbk' if '.' in dbname else dbname+'.fbk' ) -# -# extbat=os.path.join(context['temp_directory'],'tmp_6392.bat') -# extlog=os.path.splitext(extbat)[0]+'.log' -# exterr=os.path.splitext(extbat)[0]+'.err' -# -# chksql="iif( upper(mon$database_name) = upper( q'{%(tmpdir)s\\%(dbname)s}' ), 'SUCCESS.', '### ERROR: DB HAS DIFFERENT NAME ###')" % locals() -# chksql=chksql.replace('^', '^^').replace(')', '^)') -# # echo select 'c: emp\\ [[[ strange ]]] folder with {{{ lot of }}} spaces^^!\\DB with very^^! ^)^)^) strange ((( name; created for core-6392.fdb' from rdb$database; -# -# runcmd=''' -# @echo off -# setlocal enabledelayedexpansion enableextensions -# set ISC_USER=%(user_name)s -# set ISC_PASSWORD=%(user_password)s -# set FB_HOME=%(fb_home)s\\\\ -# -# set tmpsql=%%~dpn0.sql -# -# del %(extlog)s 2>nul -# -# mkdir "%(tmpdir)s" 2>nul -# if exist "%(tmpdir)s" ( -# echo Directory created OK. -# ) else ( -# echo Could NOT create directory "%(tmpdir)s". ABEND. -# goto :final -# ) -# -# if exist "%(tmpdir)s\\%(dbname)s" del "%(tmpdir)s\\%(dbname)s" -# -# ( -# echo set bail on; -# echo create database "%(tmpdir)s\\%(dbname)s"; -# echo set list on; -# echo select %(chksql)s as "CHECK POINT. Result:" from mon$database; -# ) > !tmpsql! -# -# echo CHECK POINT. Trying to create database. -# !FB_HOME!isql.exe -q -i !tmpsql! -# -# del !tmpsql! -# -# echo CHECK POINT. Trying to BACKUP without "-se" switch. -# !FB_HOME!gbak.exe -b -verbi 999999 -st tdrw localhost:"%(tmpdir)s\\%(dbname)s" "%(tmpdir)s\\%(bkname)s" -# if exist "%(tmpdir)s\\%(bkname)s" ( -# echo CHECK POINT. Trying to restore without "-se". -# !FB_HOME!gbak.exe -rep -verbi 999999 -st tdrw "%(tmpdir)s\\%(bkname)s" localhost:"%(tmpdir)s\\%(dbname)s" -# ) -# -# echo. -# echo CHECK POINT. Trying to backup using gbak WITH "-se" switch. -# if exist "%(tmpdir)s\\%(bkname)s" del "%(tmpdir)s\\%(bkname)s" -# !FB_HOME!gbak.exe -b -verbi 999999 -st tdrw -se localhost:service_mgr "%(tmpdir)s\\%(dbname)s" "%(tmpdir)s\\%(bkname)s" -# if exist "%(tmpdir)s\\%(bkname)s" ( -# echo CHECK POINT. Trying to restore using gbak WITH "-se" switch. -# !FB_HOME!gbak.exe -rep -verbi 999999 -st tdrw -se localhost:service_mgr "%(tmpdir)s\\%(bkname)s" "%(tmpdir)s\\%(dbname)s" -# ) -# -# echo. -# echo CHECK POINT. Trying to backup using fbsvcmgr. -# if exist "%(tmpdir)s\\%(bkname)s" del "%(tmpdir)s\\%(bkname)s" -# -# !FB_HOME!fbsvcmgr.exe localhost:service_mgr action_backup dbname "%(tmpdir)s\\%(dbname)s" bkp_file "%(tmpdir)s\\%(bkname)s" verbint 999999 bkp_stat tdrw -# if exist "%(tmpdir)s\\%(bkname)s" ( -# echo CHECK POINT. Trying to restore using fbsvcmgr. -# !FB_HOME!fbsvcmgr.exe localhost:service_mgr action_restore res_replace bkp_file "%(tmpdir)s\\%(bkname)s" dbname "%(tmpdir)s\\%(dbname)s" verbint 999999 res_stat tdrw -# ) -# -# :final -# if exist "%(tmpdir)s\\%(dbname)s" del "%(tmpdir)s\\%(dbname)s" -# if exist "%(tmpdir)s\\%(bkname)s" del "%(tmpdir)s\\%(bkname)s" -# rmdir "%(tmpdir)s" -# echo Bye-bye from %%~f0 -# ''' % dict(globals(), **locals()) -# -# f_extbat=open( extbat, 'w' ) -# f_extbat.write(runcmd) -# flush_and_close(f_extbat) -# -# f_extlog=open( extlog, 'w' ) -# subprocess.call( [ extbat ], stdout = f_extlog, stderr = subprocess.STDOUT ) -# flush_and_close(f_extlog) -# -# allowed_patterns = [ re.compile(p, re.IGNORECASE) for p in -# ( -# 'check\\s+point' -# ,'closing\\s+file(,)?\\s+committing(,)?\\s+.*finishing' -# ,'finishing(,)?\\s+closing(,)?\\s+.*going\\s+home' -# ) -# ] -# -# with open(f_extlog.name, 'r') as f: -# for line in f: -# if 'gbak: ERROR' in line: -# print('UNEXPECTED ERROR occured: ' + line) -# else: -# for p in allowed_patterns: -# if p.search(line): -# print( (line if 'CHECK POINT' in line else p.search(line).group() ) ) -# -# # CLEANUP -# ######### -# time.sleep(1) -# #cleanup( [extbat, extlog] ) -# -#--- + shutil.copy2(act.db.db_path, str(p_work)) + tmp_fdb = Path(p_work, Path(act.db.db_path).name) + tmp_fbk = Path(p_work, Path(act.db.db_path).stem + ". fbk") + + error_pattern = re.compile(r'gbak:\s*ERROR(:)?', re.IGNORECASE) + successful_backup_pattern = re.compile(r'gbak:closing file, committing, and finishing. \d+ bytes written', re.IGNORECASE) + successful_restore_pattern = re.compile( r'gbak:finishing, closing, and going home', re.IGNORECASE ) + + #------------------------------------------------------- + # Backup using FB services API: + # + act.svcmgr(switches=[ 'action_backup', 'dbname', str(tmp_fdb), 'bkp_file', str(tmp_fbk), 'verbint', '999999']) + svc_log = act.stdout + svc_err = act.stderr + + for line in svc_err.split('\n'): + print(line) + + for line in svc_log.split('\n'): + if successful_backup_pattern.search(line): + print(expected_backup_out) + break + + act.expected_stdout = expected_backup_out + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + act.reset() + + #------------------------------------------------------- + # Restore using FB services API: + # + act.svcmgr(switches=[ 'action_restore', 'bkp_file', str(tmp_fbk), 'dbname', str(tmp_fdb), 'verbint', '999999', 'res_replace']) + svc_log = act.stdout + svc_err = act.stderr + + for line in svc_err.split('\n'): + print(line) + + for line in svc_log.split('\n'): + if successful_restore_pattern.search(line): + print(expected_restore_out) + break + + act.expected_stdout = expected_restore_out + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + act.reset() + + #------------------------------------------------------- + # Backup via 'gbak -se' (this failed on 4.0.0.2173): + # + act.gbak(switches=['-b', '-se', 'localhost:service_mgr', '-verbint', '99999', '-y', str(bkp_log), str(tmp_fdb), str(tmp_fbk)]) + with open(bkp_log, 'r') as f: + for line in f: + if error_pattern.search(line): + print('Backup FAILED:', line) + break + if successful_backup_pattern.search(line): + print(expected_backup_out) + break + act.expected_stdout = expected_backup_out + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + act.reset() + + #------------------------------------------------------- + # Restore via 'gbak -se': + # + act.gbak(switches=['-rep', '-se', 'localhost:service_mgr', '-verbint', '99999', '-y', str(res_log), str(tmp_fbk), str(tmp_fdb) ]) + with open(res_log, 'r') as f: + for line in f: + if error_pattern.search(line): + print('Restore FAILED:', line) + break + if successful_restore_pattern.search(line): + print(expected_restore_out) + break + act.expected_stdout = expected_restore_out + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + act.reset()