6
0
mirror of https://github.com/FirebirdSQL/firebird-qa.git synced 2025-01-23 05:53:06 +01:00
firebird-qa/tests/bugs/core_6248_test.py

148 lines
5.8 KiB
Python

#coding:utf-8
"""
ID: issue-6492
ISSUE: 6492
TITLE: A number of errors when database name is longer than 255 symbols
DESCRIPTION:
Test verifies that one may to create DB with total path plus name length L = 255 and 259 characters.
Each DB is then subject for 'gbak -b', 'gbak -c', 'gstat -h', 'gfix -sweep' and 'gfix -v -full'.
All these commands must NOT issue something to their STDERR.
STDOUT-log of initial SQL must contain full DB name.
Changed part of firebird.log for SWEEP and VALIDATION also must have full DB name (this is verified using regexp):
+[tab]Database: C:\\FBTESTING\\QA\\FBT-REPO\\TMP\\ABC.FDB // for validation
+[tab]Database "C:\\FBTESTING\\QA\\FBT-REPO\\TMP\\ABC.FDB // for sweep
STDOUT-logs of backup, restore and gstat currently (09-mar-2020) have only truncated name (~235...241 chars).
This may change in the future if FB developers will decide to fix this small inconveniences.
For L=259 we must see in backup log following phrase:
gbak:text for attribute 7 is too large in put_asciz(), truncating to 255 bytes
- but currently this is not checked here.
JIRA: CORE-6248
"""
import pytest
import re
import time
from difflib import unified_diff
from firebird.qa import *
from firebird.driver import SrvRepairFlag
init_script = """
set list on;
create exception exc_dbname_diff q'{Value in mon$database.mon$database_name differs from rdb$get_context('SYSTEM', 'DB_NAME'):@1@2@3=== vs ===@4@5}';
set term ^;
execute block returns(
mon_database_column varchar(260)
,sys_context_db_name varchar(260)
) as
declare lf char(1) = x'0A';
begin
select
mon$database_name as mon_database_column
from mon$database
into mon_database_column;
sys_context_db_name = rdb$get_context('SYSTEM', 'DB_NAME');
if ( substring( sys_context_db_name from 1 for 255 ) is distinct from mon_database_column ) then
begin
exception exc_dbname_diff using(
lf
,mon_database_column
,lf
,lf
,sys_context_db_name
);
end
suspend;
end
^
set term ;^
commit;
"""
db = db_factory()
act = python_act('db')
expected_stdout = """
ddl : found at least 255 characters
backup : found truncated DB name.
restore : found truncated DB name.
gstat : found truncated DB name.
fblog_diff_sweep : found at least 255 characters
fblog_diff_validate : found at least 255 characters
"""
@pytest.fixture
def test_db(request: pytest.FixtureRequest, db_path) -> Database:
required_name_len = request.param[0]
chars2fil = request.param[1]
filename = (chars2fil * 1000)[:required_name_len - len(str(db_path)) - 4] + '.fdb'
db = Database(db_path, filename)
db.create()
yield db
db.drop()
MINIMAL_LEN_TO_SHOW = 255
PATTERN = re.compile('\\+\\s+Database[:]{0,1}\\s+"{0,1}', re.IGNORECASE)
def check_filename_presence(lines, *, log_name: str, db: Database):
filename = str(db.db_path) # To convert Path to string
for line in lines:
if log_name not in ('fblog_diff_sweep', 'fblog_diff_validate') or line.startswith('+') and PATTERN.search(line):
if filename[:MINIMAL_LEN_TO_SHOW].upper() in line.upper():
print(f'{log_name} : found at least {str(MINIMAL_LEN_TO_SHOW)} characters')
return
elif filename[:128].upper() in line.upper():
print(f'{log_name} : found truncated DB name.')
return
print(f'{log_name} : DB NAME NOT FOUND')
@pytest.mark.version('>=4.0')
@pytest.mark.parametrize('test_db', [pytest.param((255, 'abc255def'), id='255'),
pytest.param((259, 'qwe259rty'), id='259')], indirect=True)
def test_1(act: Action, test_db: Database, capsys):
# INIT test
act.isql(switches=['-q', test_db.dsn], input=init_script, connect_db=False)
check_filename_presence(act.stdout.splitlines(), log_name='ddl', db=test_db)
# GBAK BACKUP test
backup_name = test_db.db_path.with_name(f"tmp_6248_backup_{len(test_db.db_path.with_suffix('').name)}.fbk")
act.reset()
act.gbak(switches=['-b', '-se', 'localhost:servce_mgr', '-v', '-st', 'tdwr', str(test_db.db_path), str(backup_name)])
check_filename_presence(act.stdout.splitlines(), log_name='backup', db=test_db)
# GBAK RESTORE test
act.reset()
act.gbak(switches=['-rep', '-se', 'localhost:servce_mgr', '-v', '-st', 'tdwr', str(backup_name), str(test_db.db_path)])
check_filename_presence(act.stdout.splitlines(), log_name='restore', db=test_db)
# GSTAT test
act.reset()
act.gstat(switches=['-h', test_db.dsn], connect_db=False)
check_filename_presence(act.stdout.splitlines(), log_name='gstat', db=test_db)
# SWEEP test
log_before = act.get_firebird_log()
with act.connect_server() as srv:
srv.database.sweep(database=test_db.db_path)
time.sleep(1) # Let firebird.log to be fulfilled with text about just finished SWEEP
log_after = act.get_firebird_log()
check_filename_presence(list(unified_diff(log_before, log_after)), log_name='fblog_diff_sweep', db=test_db)
# VALIDATE test
log_before = act.get_firebird_log()
with act.connect_server() as srv:
srv.database.repair(database=test_db.db_path, flags=SrvRepairFlag.FULL | SrvRepairFlag.VALIDATE_DB)
time.sleep(1) # Let firebird.log to be fulfilled with text about just finished VALIDATION
log_after = act.get_firebird_log()
check_filename_presence(list(unified_diff(log_before, log_after)), log_name='fblog_diff_validate', db=test_db)
# Check
act.reset()
act.expected_stdout = expected_stdout
act.stdout = capsys.readouterr().out
assert act.clean_stdout == act.clean_expected_stdout