6
0
mirror of https://github.com/FirebirdSQL/firebird-qa.git synced 2025-01-22 13:33:07 +01:00

Added/Updated tests\bugs\core_4964_test.py: Expected ISQL output must be compared with filtered capsys.readouterr().out rather than with act.stdout. Noted by Dimitry Sibiryakov, https://github.com/FirebirdSQL/firebird-qa/issues/27

This commit is contained in:
pavel-zotov 2024-07-31 23:14:40 +03:00
parent d44c33b9e5
commit b9ac7029fe

View File

@ -1,140 +1,186 @@
#coding:utf-8 #coding:utf-8
""" """
ID: issue-5255 ID: issue-5255
ISSUE: 5255 ISSUE: 5255
JIRA: CORE-4964 JIRA: CORE-4964
FBTEST: bugs.core_4964 FBTEST: bugs.core_4964
TITLE: Real errors during connect to security database are hidden by Srp user manager. Errors should be logged no matter what AuthServer is used TITLE: Real errors during connect to security database are hidden by Srp user manager. Errors should be logged no matter what AuthServer is used
DESCRIPTION: DESCRIPTION:
Test does following: Test does following:
1) creates temporary user using plugin Srp (in order to avoid occasional connect as SYSDBA using Legacy plugin); 1) creates temporary user using plugin Srp (in order to avoid occasional connect as SYSDBA using Legacy plugin);
2) makes copy of test DB to file which is specified n databases.conf as database for alias defined by variable with name REQUIRED_ALIAS 2) makes copy of test DB to file which is specified n databases.conf as database for alias defined by variable with name REQUIRED_ALIAS
(its value: 'tmp_4964_alias'; test will try to connect to this file via ALIAS from pre-created databases.conf); (its value: 'tmp_4964_alias'; test will try to connect to this file via ALIAS from pre-created databases.conf);
3) uses pre-created databases.conf which has alias and SecurityDatabase parameter in its details. 3) uses pre-created databases.conf which has alias and SecurityDatabase parameter in its details.
This parameter that points to existing file that for sure can NOT be a Firebird database This parameter that points to existing file that for sure can NOT be a Firebird database
(file $(dir_conf)/firebird.msg is used for this purpose). (file $(dir_conf)/firebird.msg is used for this purpose).
Then we: Then we:
1) obtain content of server firebird.log; 1) obtain content of server firebird.log;
2) try to make connect to alias <tmp_alias> and (as expected) get error; 2) try to make connect to alias <tmp_alias> and (as expected) get error;
3) obtain again content of server firebird.log and compare to origin one. 3) obtain again content of server firebird.log and compare to origin one.
NOTES: NOTES:
[02.08.2022] pzotov [02.08.2022] pzotov
1. One need to be sure that firebird.conf does NOT contain DatabaseAccess = None. 1. One need to be sure that firebird.conf does NOT contain DatabaseAccess = None.
2. Value of REQUIRED_ALIAS must be EXACTLY the same as alias specified in the pre-created databases.conf 2. Value of REQUIRED_ALIAS must be EXACTLY the same as alias specified in the pre-created databases.conf
(for LINUX this equality is case-sensitive, even when aliases are compared!) (for LINUX this equality is case-sensitive, even when aliases are compared!)
3. Make sure that firebird was launched by user who is currently runs this test. 3. Make sure that firebird was launched by user who is currently runs this test.
Otherwise shutil.copy2() failes with "[Errno 13] Permission denied". Otherwise shutil.copy2() failes with "[Errno 13] Permission denied".
4. Content of databases.conf must be taken from $QA_ROOT/files/qa-databases.conf (one need to replace it before every test session). 4. Content of databases.conf must be taken from $QA_ROOT/files/qa-databases.conf (one need to replace it before every test session).
Discussed with pcisar, letters since 30-may-2022 13:48, subject: Discussed with pcisar, letters since 30-may-2022 13:48, subject:
"new qa, core_4964_test.py: strange outcome when use... shutil.copy() // comparing to shutil.copy2()" "new qa, core_4964_test.py: strange outcome when use... shutil.copy() // comparing to shutil.copy2()"
Checked on 5.0.0.591, 4.0.1.2692, 3.0.8.33535 - both on Windows and Linux. [31.07.2024] pzotov
""" Replaced assert for ISQL output: added diff_patterns that must filter STDERR because we have to suppress message with text
"file ... is not a valid database" as it can be seen only in dev-builds.
import re Expected ISQL output must be compared with filtered capsys.readouterr().out rather than with act.stdout
import time Noted by Dimitry Sibiryakov, https://github.com/FirebirdSQL/firebird-qa/issues/27
from pathlib import Path
from difflib import unified_diff Checked on 5.0.0.591, 4.0.1.2692, 3.0.8.33535 - both on Windows and Linux.
"""
import pytest
from firebird.qa import * import re
import time
substitutions = [('[ \t]+', ' '), ('file .* is not a valid database', 'file is not a valid database'), ] from pathlib import Path
from difflib import unified_diff
REQUIRED_ALIAS = 'tmp_core_4964_alias'
import pytest
db = db_factory() from firebird.qa import *
act = python_act('db', substitutions=substitutions)
tmp_user = user_factory('db', name='tmp$c4964', password='123', plugin = 'Srp') substitutions = [
('[ \t]+', ' ')
expected_stdout_isql = """ ,('(-)?file .* is not a valid database', 'file is not a valid database')
Statement failed, SQLSTATE = 08006 ]
Error occurred during login, please check server firebird.log for details
""" REQUIRED_ALIAS = 'tmp_core_4964_alias'
expected_stdout_log_diff = """ db = db_factory()
Authentication error act = python_act('db', substitutions = substitutions)
file is not a valid database tmp_user = user_factory('db', name='tmp$c4964', password='123', plugin = 'Srp')
"""
expected_stdout_isql = """
@pytest.mark.version('>=3.0') Statement failed, SQLSTATE = 08006
def test_1(act: Action, tmp_user: User, capsys): Error occurred during login, please check server firebird.log for details
"""
fblog_1 = act.get_firebird_log()
expected_stdout_log_diff = """
# Scan line-by-line through databases.conf, find line starting with REQUIRED_ALIAS and extract name of file that Authentication error
# must be created in the $(dir_sampleDb)/qa/ folder. This name will be used further as target database (tmp_fdb). file is not a valid database
# NOTE: we have to SKIP lines which are commented out, i.e. if they starts with '#': """
p_required_alias_ptn = re.compile( '^(?!#)((^|\\s+)' + REQUIRED_ALIAS + ')\\s*=\\s*\\$\\(dir_sampleDb\\)/qa/', re.IGNORECASE )
fname_in_dbconf = None @pytest.mark.version('>=3.0')
def test_1(act: Action, tmp_user: User, capsys):
with open(act.home_dir/'databases.conf', 'r') as f:
for line in f: fblog_1 = act.get_firebird_log()
if p_required_alias_ptn.search(line):
# If databases.conf contains line like this: # Scan line-by-line through databases.conf, find line starting with REQUIRED_ALIAS and extract name of file that
# tmp_4964_alias = $(dir_sampleDb)/qa/tmp_qa_4964.fdb # must be created in the $(dir_sampleDb)/qa/ folder. This name will be used further as target database (tmp_fdb).
# - then we extract filename: 'tmp_qa_4964.fdb' (see below): # NOTE: we have to SKIP lines which are commented out, i.e. if they starts with '#':
fname_in_dbconf = Path(line.split('=')[1].strip()).name p_required_alias_ptn = re.compile( '^(?!#)((^|\\s+)' + REQUIRED_ALIAS + ')\\s*=\\s*\\$\\(dir_sampleDb\\)/qa/', re.IGNORECASE )
break fname_in_dbconf = None
# if 'fname_in_dbconf' remains undefined here then propably REQUIRED_ALIAS not equals to specified in the databases.conf! with open(act.home_dir/'databases.conf', 'r') as f:
# for line in f:
assert fname_in_dbconf if p_required_alias_ptn.search(line):
# If databases.conf contains line like this:
# Full path + filename of database to which we will try to connect: # tmp_4964_alias = $(dir_sampleDb)/qa/tmp_qa_4964.fdb
# # - then we extract filename: 'tmp_qa_4964.fdb' (see below):
tmp_fdb = Path( act.vars['sample_dir'], 'qa', fname_in_dbconf ) fname_in_dbconf = Path(line.split('=')[1].strip()).name
break
# PermissionError: [Errno 13] Permission denied --> probably because
# Firebird was started by root rather than current (non-privileged) user. # if 'fname_in_dbconf' remains undefined here then propably REQUIRED_ALIAS not equals to specified in the databases.conf!
# #
tmp_fdb.write_bytes(act.db.db_path.read_bytes()) assert fname_in_dbconf
check_sql = f''' # Full path + filename of database to which we will try to connect:
set bail on; #
set list on; tmp_fdb = Path( act.vars['sample_dir'], 'qa', fname_in_dbconf )
connect '{act.host+":" if act.host else ""}{tmp_fdb}' user {tmp_user.name} password {tmp_user.password};
-- This can occus only if we databases.conf contains {REQUIRED_ALIAS} # PermissionError: [Errno 13] Permission denied --> probably because
-- but without reference to invalid security DB (e.g., alias without curly braces at all): # Firebird was started by root rather than current (non-privileged) user.
select mon$database_name as "UNEXPECTED CONNECTION:" from mon$database; #
quit; tmp_fdb.write_bytes(act.db.db_path.read_bytes())
'''
check_sql = f'''
############################################################################################################### set bail on;
# POINT-1: check that ISQL raises: set list on;
# "SQLSTATE = 08006 / Error occurred during login, please check server firebird.log ..." connect '{act.host+":" if act.host else ""}{tmp_fdb}' user {tmp_user.name} password {tmp_user.password};
# -- This can occus only if we databases.conf contains {REQUIRED_ALIAS}
act.expected_stdout = expected_stdout_isql -- but without reference to invalid security DB (e.g., alias without curly braces at all):
try: select mon$database_name as "UNEXPECTED CONNECTION:" from mon$database;
act.isql(switches = ['-q'], input = check_sql, connect_db=False, credentials = False, combine_output = True) quit;
finally: '''
tmp_fdb.unlink()
###############################################################################################################
assert act.clean_stdout == act.clean_expected_stdout # POINT-1: check that ISQL raises:
act.reset() # "SQLSTATE = 08006 / Error occurred during login, please check server firebird.log ..."
#
time.sleep(1) # Allow content of firebird log be fully flushed on disk.
fblog_2 = act.get_firebird_log() # release build:
# ==================================
diff_patterns = [ # Statement failed, SQLSTATE = 08006
"\\+\\s+Authentication error", # Error occurred during login, please check server firebird.log for details
"\\+\\s+file .* is not a valid database", # ==================================
]
diff_patterns = [re.compile(s) for s in diff_patterns] # dev-build:
# ==================================
for line in unified_diff(fblog_1, fblog_2): # Statement failed, SQLSTATE = 08006
if line.startswith('+'): # Error occurred during login, please check server firebird.log for details
if act.match_any(line, diff_patterns): # -file ... is not a valid database
print(line.split('+')[-1]) # ==================================
# Last line ("file ... is not a valid database") will be suppressed by substitutions set:
############################################################################################################### #
# POINT-2: check that diff between firebird.log initial and current content has phrases
# 'Authentication error' and '... file is not a valid database': isql_err_diff_patterns = [
# "Statement failed, SQLSTATE = 08006"
act.expected_stdout = expected_stdout_log_diff ,"Error occurred during login, please check server firebird.log for details"
act.stdout = capsys.readouterr().out ]
assert act.clean_stdout == act.clean_expected_stdout isql_err_diff_patterns = [re.compile(s) for s in isql_err_diff_patterns]
act.reset()
act.expected_stdout = expected_stdout_isql
try:
act.isql(switches = ['-q'], input = check_sql, connect_db=False, credentials = False, combine_output = True)
finally:
tmp_fdb.unlink()
# ::: NB :::
# Expected ISQL output must be compared with filtered capsys.readouterr().out rather than with act.stdout
for line in act.stdout.splitlines():
if act.match_any(line, isql_err_diff_patterns):
print(line)
act.stdout = capsys.readouterr().out
assert act.clean_stdout == act.clean_expected_stdout
act.reset()
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
time.sleep(1) # Allow content of firebird log be fully flushed on disk.
fblog_2 = act.get_firebird_log()
fb_log_diff_patterns = [
"\\+\\s+Authentication error"
,"\\+\\s+file .* is not a valid database"
]
fb_log_diff_patterns = [re.compile(s) for s in fb_log_diff_patterns]
# BOTH release and dev build will print in firebird.log:
# <hostname> <timestamp>
# Authentication error
# file .* is not a valid database
#
for line in unified_diff(fblog_1, fblog_2):
if line.startswith('+'):
if act.match_any(line, fb_log_diff_patterns):
print(line.split('+')[-1])
###############################################################################################################
# POINT-2: check that diff between firebird.log initial and current content has phrases
# 'Authentication error' and '... file is not a valid database':
#
act.expected_stdout = expected_stdout_log_diff
act.stdout = capsys.readouterr().out
assert act.clean_stdout == act.clean_expected_stdout
act.reset()