6
0
mirror of https://github.com/FirebirdSQL/firebird-qa.git synced 2025-02-02 02:40:42 +01:00

Added/Updated bugs\core_6147_test.py. Checked on 5.0.0.591, 4.0.1.2692, 3.0.8.33535 - both on Windows and Linux.

This commit is contained in:
zotov 2022-08-07 11:27:02 +03:00
parent f0da63fc35
commit a5bf010081

View File

@ -2,364 +2,221 @@
""" """
ID: issue-6396 ID: issue-6396
ISSUE: 6396 ISSUE: https://github.com/FirebirdSQL/firebird/issues/6396
TITLE: PLG$SRP table, PLG$SRP_VIEW View instructions are strangely added in the metadata TITLE: PLG$SRP table, PLG$SRP_VIEW View instructions are strangely added in the metadata script extracted when Windows trusted authentication is enabled
script extracted when Windows trusted authentication is enabled
DESCRIPTION: DESCRIPTION:
References to the table PLG$SRP and view PLG$SRP_VIEW *always* present in extracted metadata,
regardless of using auth plugin (and this is NOT a bug!).
Fix was introduced in 4.0.0.2087: extracted metadata must contain "OR ALTER" clause in: ## ACHTUNG ## Ticket title ("PLG$SRP table, PLG$SRP_VIEW View instructions are strangely added ...")
CREATE OR ALTER GLOBAL MAPPING TRUSTED_AUTH_C6147 ... must be REPLACED because references to the table PLG$SRP and view PLG$SRP_VIEW *always* present
^^^^^^^^ in extracted metadata, and this is EXPECTED, i.e. this is not error!
The only change that was in the FB source related to this ticket is appearance of 'OR ALTER'
phrase in the 'CREATE [OR ALTER] GLOBAL MAPPING ...' statement.
(i.e. phase "OR ALTER" missed in extracted metadata before that).
Builds before 4.0.0.2084 did not add this clause in extracted metadata script (checked 4.0.0.2076). Builds before 4.0.0.2084 did not add this clause in extracted metadata script (checked 4.0.0.2076).
(see also discussion with Alex, 02-jun-2020 08:23). COnfirmed problem also on 3.0.5.33115 (date of build: 26-mar-2019).
### NB ### Comparison between major FB and builds (3.0.5.33212 vs 3.0.6.33326 and 4.0.0.2076 vs 4.0.0.2084):
For unclear reason ALTER EXTERNAL CONNECTIONS POOL CLEAR ALL + DROP DATABASE do not work as expected in this test: see letter to Alex, 01-JUL-2020 21:38. Reply from Alex: 02-JUL-2020 08:23.
test DB remains opened by firebird.exe about 5...7 seconds after test finish, and 'drop database' does not issues any error.
Because of this it was decided to forcedly change DB state to full shutdown in order to have ability to drop it.
22.02.2021: perhaps, this was somehow related to core-6441.
NOTES FOR WINDOWS: fix for FB 4.x
################## https://github.com/FirebirdSQL/firebird/commit/dbc28a88c0b96964c19f9a8fa76f7f3dc1db16c4
We create copy of %FIREBIRD_HOME%\\database.conf and change it content by adding lines: Date: 01-Jul-2020 18:06
tmp_alias_6147 = ... Changed paths: M src/isql/show.epp
{ Partial f_ix for CORE-6147: be smart when dealing with global mappings in metadata script
SecurityDatabase = tmp_alias_6147
}
Then we create trest DB in embedded mode, create SYSDBA that belongs to this DB and create global mapping.
We check content of rdb$auth_mapping table after this step in order to ensure that mapping was actually created.
After this we do connect to DB using Win_SSPI and extract metadata.
NOTES FOR LINUX: fix for FB 3.x
################ https://github.com/FirebirdSQL/firebird/commit/66499fdbeed7fe2e1765a01e7d599553c3330b0e
03-mar-2021. This test can run on Linux but we have to use plugin = Srp instead of win_sspi. Date: 09-Jul-2020 18:10
This is done by check result of os.name (see below). Changed paths: M src/isql/show.epp
Local mapping (i.e. in RDB$DATABASE) will *not* be created in this case (in contrary to win_sspi), Backported f_ix for CORE-6147: script with extracted metadata may fail on global mapping
thus we create and drop it "manually" in order to pass expected results check.
Kind of auth plugin does not matter (i.e. win_sspi or srp), so Srp was selected for running this test
both on Windows and Linux.
Test uses pre-created databases.conf which has alias (see variable REQUIRED_ALIAS) and SecurityDatabase in its details
which points to that alias, thus making such database be self-security.
Database file for that alias must NOT exist in the QA_root/files/qa/ subdirectory: it will be created here.
Self-security database allows us to create GLOBAL mapping without worrying about how it will be removed on test finish.
Checked on: Checked on:
* Windows: 4.0.0.2377 SS/CS (done for both win_sspi and Srp, but only win_sspi is used in this test for Windows) * Windows: 4.0.0.2377 SS/CS (done for both win_sspi and Srp, but only win_sspi is used in this test for Windows)
* Linux: 4.0.0.2377 SS/CS (done for Srp) * Linux: 4.0.0.2377 SS/CS (done for Srp)
JIRA: CORE-6147 JIRA: CORE-6147
FBTEST: bugs.core_6147 FBTEST: bugs.core_6147
NOTES:
[07.08.2022] pzotov
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
(for LINUX this equality is case-sensitive, even when aliases are compared!)
3. 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:
"new qa, core_4964_test.py: strange outcome when use... shutil.copy() // comparing to shutil.copy2()"
::: NOTE :::
TEST CAN AND MUST BE SIMPLIFIED.
There is mapping_factory() in the QA plugin, and it can be used to create/drop GLOBAL mapping.
To be discussed with pcisar.
Checked on 5.0.0.591, 4.0.1.2692, 3.0.8.33535 - both on Windows and Linux.
""" """
import os
import re
import locale
import subprocess
from pathlib import Path
import time
import pytest import pytest
from firebird.qa import * from firebird.qa import *
db = db_factory() # Name of alias for self-security DB in the QA_root/files/qa-databases.conf.
# This file must be copied manually to each testing FB homw folder, with replacing
# databases.conf there:
#
REQUIRED_ALIAS = 'tmp_core_6147_alias'
db = db_factory()
act = python_act('db', substitutions=[('[ \t]+', ' '), ('.*===.*', ''), ('PLUGIN .*', 'PLUGIN')]) act = python_act('db', substitutions=[('[ \t]+', ' '), ('.*===.*', ''), ('PLUGIN .*', 'PLUGIN')])
expected_stdout = """ fn_meta_log = temp_file('tmp_core_6147-meta.log')
AFTER_MADE_MAPPING: MAP_NAME MAP_TYPE FROM_TYPE MAP_FROM TO_TYPE MAP_TO fn_meta_err = temp_file('tmp_core_6147-meta.err')
AFTER_MADE_MAPPING: =============================== ========== ========== ========== ======= ==========
AFTER_MADE_MAPPING: TRUSTED_AUTH_C6147 local USER * 0 <null>
AFTER_MADE_MAPPING: TRUSTED_AUTH_C6147 global USER * 0 <null>
AFTER_MADE_MAPPING: Records affected: 2
EXTRACTED_METADATA: CREATE MAPPING TRUSTED_AUTH_C6147 USING PLUGIN #@pytest.mark.version('>=3.0.7')
EXTRACTED_METADATA: CREATE OR ALTER GLOBAL MAPPING TRUSTED_AUTH_C6147 USING PLUGIN @pytest.mark.version('>=3.0')
def test_1(act: Action, fn_meta_log: Path, fn_meta_err: Path, capsys):
AFTER_DROP_MAPPING: Records affected: 0 # Scan line-by-line through databases.conf, find line starting with REQUIRED_ALIAS and extract name of file that
# must be created in the $(dir_sampleDb)/qa/ folder. This name will be used further as target database (tmp_fdb).
# 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
""" with open(act.home_dir/'databases.conf', 'r') as f:
for line in f:
if p_required_alias_ptn.search(line):
# If databases.conf contains line like this:
# tmp_6147_alias = $(dir_sampleDb)/qa/tmp_core_6147.fdb
# - then we extract filename: 'tmp_core_6147.fdb' (see below):
fname_in_dbconf = Path(line.split('=')[1].strip()).name
break
@pytest.mark.skip('FIXME: databases.conf') # if 'fname_in_dbconf' remains undefined here then propably REQUIRED_ALIAS not equals to specified in the databases.conf!
@pytest.mark.version('>=4.0') #
def test_1(act: Action): assert fname_in_dbconf
pytest.fail("Not IMPLEMENTED")
# test_script_1 # Full path + filename of database to which we will try to connect:
#--- #
# tmp_fdb = Path( act.vars['sample_dir'], 'qa', fname_in_dbconf )
# import os
# import subprocess PLUGIN_FOR_MAPPING = 'Srp'
# import datetime MAPPING_NAME = 'trusted_auth_c6147'
# import time
# import shutil sql_txt = f'''
# import re set bail on;
# from fdb import services set list on;
# create database '{REQUIRED_ALIAS}' user {act.db.user};
# this_fdb = db_conn.database_name select
# m.mon$sec_database as mon_sec_db
# if os.name == 'nt': from mon$database m;
# # On Windows we test what it was initially described in the ticket (trusted auth.): commit;
# PLUGIN_FOR_MAPPING = 'win_sspi'
# else: create or alter global mapping {MAPPING_NAME} using plugin {PLUGIN_FOR_MAPPING} from any user to user;
# # On Linux currently we can check only Srp plugin commit;
# # but results must be the same as for win_sspi:
# PLUGIN_FOR_MAPPING = 'Srp' recreate view v_map_info as
# select
# map_name
# # 23.08.2020: !!! REMOVING OS-VARIABLE ISC_USER IS MANDATORY HERE !!! ,map_type
# # This variable could be set by other .fbts which was performed before current within batch mode (i.e. when fbt_run is called from <rundaily>) -- ,map_plugin
# # NB: os.unsetenv('ISC_USER') actually does NOT affect on content of os.environ dictionary, see: https://docs.python.org/2/library/os.html ,from_type
# # We have to remove OS variable either by os.environ.pop() or using 'del os.environ[...]', but in any case this must be enclosed intro try/exc: ,map_from
# #os.environ.pop('ISC_USER') ,to_type
# try: ,map_to
# del os.environ["ISC_USER"] from
# except KeyError as e: (
# pass select
# 'LOCAL' as map_type
# db_conn.close() ,rdb$map_name as map_name
# ,rdb$map_plugin as map_plugin
# #-------------------------------------------- ,rdb$map_from_type as from_type
# ,rdb$map_from as map_from
# def flush_and_close( file_handle ): ,rdb$map_to_type as to_type
# # https://docs.python.org/2/library/os.html#os.fsync ,rdb$map_to as map_to
# # If you're starting with a Python file object f, from rdb$auth_mapping
# # first do f.flush(), and UNION ALL
# # then do os.fsync(f.fileno()), to ensure that all internal buffers associated with f are written to disk. select
# global os 'GLOBAL'
# ,sec$map_name
# file_handle.flush() ,sec$map_plugin
# if file_handle.mode not in ('r', 'rb') and file_handle.name != os.devnull: ,sec$map_from_type
# # otherwise: "OSError: [Errno 9] Bad file descriptor"! ,sec$map_from
# os.fsync(file_handle.fileno()) ,sec$map_to_type
# file_handle.close() ,sec$map_to
# from sec$global_auth_mapping
# #-------------------------------------------- ) t
# where
# def cleanup( f_names_list ): t.map_name = upper('{MAPPING_NAME}')
# global os and upper(t.map_plugin) = upper('{PLUGIN_FOR_MAPPING}')
# for f in f_names_list: ;
# if type(f) == file: commit;
# del_name = f.name
# elif type(f) == str: set count on;
# del_name = f select * from v_map_info;
# else: quit;
# print('Unrecognized type of element:', f, ' - can not be treated as file.') '''
# del_name = None
# expected_stdout_isql = f'''
# if del_name and os.path.isfile( del_name ): MON_SEC_DB Self
# os.remove( del_name )
# MAP_NAME TRUSTED_AUTH_C6147
# #-------------------------------------------- MAP_TYPE LOCAL
# FROM_TYPE USER
# svc = services.connect(host='localhost', user= user_name, password= user_password) MAP_FROM *
# fb_home = svc.get_home_directory() TO_TYPE 0
# svc.close() MAP_TO <null>
# # Resut: fb_home is full path to FB instance home (with trailing slash).
# MAP_NAME TRUSTED_AUTH_C6147
# dts = datetime.datetime.now().strftime("%y%m%d_%H%M%S") MAP_TYPE GLOBAL
# FROM_TYPE USER
# dbconf = os.path.join( fb_home, 'databases.conf') MAP_FROM *
# dbcbak = os.path.join( fb_home, 'databases_'+dts+'.bak') TO_TYPE 0
# MAP_TO <null>
# shutil.copy2( dbconf, dbcbak ) Records affected: 2
# '''
# tmp_fdb=os.path.join(context['temp_directory'],'tmp_6147.fdb') try:
# cleanup( (tmp_fdb,) ) act.expected_stdout = expected_stdout_isql
# act.isql(switches = ['-q'], input = sql_txt, connect_db=False, credentials = False, combine_output = True, io_enc = locale.getpreferredencoding())
# text2app='''
# assert act.clean_stdout == act.clean_expected_stdout
# # Temporarily added by fbtest, CORE-6147. Should be removed auto: act.reset()
# ##############################
# tmp_alias_6147 = %(tmp_fdb)s with fn_meta_log.open(mode='w') as meta_out, fn_meta_err.open(mode='w') as meta_err:
# { # could not find how properly call act.extract_meta with ANOTHER database (different from currently created).
# SecurityDatabase = tmp_alias_6147 subprocess.call( [ act.vars['isql'],'-x', '-user', act.db.user, '-pas', act.db.password, REQUIRED_ALIAS ],
# } stdout = meta_out,
# ############################## stderr = meta_err
# ''' % locals() )
# for g in (fn_meta_log, fn_meta_err):
# f_dbconf=open( dbconf, 'a') with g.open() as f:
# f_dbconf.seek(0, 2) for line in f:
# f_dbconf.write( text2app ) if line.split():
# flush_and_close( f_dbconf ) if g == fn_meta_log:
# if ' MAPPING ' in line:
# print(f'{line}')
# SHOW_MAP_INFO_QUERY = ''' else:
# set count on; print(f'UNEXPECTED MATADATA STDOUT: {line}')
# -- set echo on;
# set width map_name 31; act.expected_stdout = f"""
# set width map_type 10; CREATE MAPPING {MAPPING_NAME.upper()} USING PLUGIN
# set width map_plugin 16; CREATE OR ALTER GLOBAL MAPPING {MAPPING_NAME.upper()} USING PLUGIN
# set width from_type 10; """
# set width map_from 10;
# set width to_type 10; finally:
# set width map_to 10; tmp_fdb.unlink()
# select * from v_map_info;
# ''' act.stdout = capsys.readouterr().out
# assert act.clean_stdout == act.clean_expected_stdout
# if PLUGIN_FOR_MAPPING == 'Srp': act.reset()
# db_connect_string = this_fdb
# sql_txt= '''
# set bail on;
# connect 'localhost:%(db_connect_string)s' user %(user_name)s password '%(user_password)s';
# commit;
# -- ::: NB :::
# -- Local mapping will NOT be created when use Srp; create it here in order to have the same results
# -- as for win_sspi:
# create or alter mapping trusted_auth_c6147 using plugin %(PLUGIN_FOR_MAPPING)s from any user to user;
# commit;
# ''' % dict(globals(), **locals())
# else:
# db_connect_string = 'tmp_alias_6147'
# sql_txt= '''
# set bail on;
# -- do NOT use 'localhost:' here! Otherwise:
# -- Statement failed, SQLSTATE = 28000
# -- Your user name and password are not defined. ...
# create database '%(db_connect_string)s' user %(user_name)s;
# create user %(user_name)s password '%(user_password)s';
# commit;
# ''' % dict(globals(), **locals())
#
# sql_txt += '''
# -- ::: NB :::
# -- When used plugin is win_sspi then *TWO* mappings will be created here: "local' (in rdb$auth_mapping)
# -- and g;pbal (in sec$global_auth_mapping). This is NOT so when used plugin = Srp (only global mapping will be made).
# create or alter global mapping trusted_auth_c6147 using plugin %(PLUGIN_FOR_MAPPING)s from any user to user;
# commit;
#
# recreate view v_map_info as
# select
# map_name
# ,map_type
# -- ,map_plugin
# ,from_type
# ,map_from
# ,to_type
# ,map_to
# from
# (
# select
# rdb$map_name as map_name
# ,'local' as map_type
# ,rdb$map_plugin as map_plugin
# ,rdb$map_from_type as from_type
# ,rdb$map_from as map_from
# ,rdb$map_to_type as to_type
# ,rdb$map_to as map_to
# from rdb$auth_mapping
# UNION ALL
# select
# sec$map_name
# ,'global'
# ,sec$map_plugin
# ,sec$map_from_type
# ,sec$map_from
# ,sec$map_to_type
# ,sec$map_to
# from sec$global_auth_mapping
# ) t
# where
# t.map_name = upper('trusted_auth_c6147')
# and t.map_plugin = upper('%(PLUGIN_FOR_MAPPING)s')
# ;
# commit;
#
# %(SHOW_MAP_INFO_QUERY)s
#
# ''' % dict(globals(), **locals())
#
# f_prepare_sql = open( os.path.join(context['temp_directory'],'tmp_6147_prepare.sql'), 'w')
# f_prepare_sql.write(sql_txt)
# flush_and_close( f_prepare_sql )
#
# f_prepare_log=open( os.path.join(context['temp_directory'],'tmp_6147_prepare.log'), 'w')
# subprocess.call( [ context['isql_path'], "-q", "-i", f_prepare_sql.name ], stdout=f_prepare_log, stderr=subprocess.STDOUT )
# flush_and_close( f_prepare_log )
#
#
# # Extract metadata from test DB:
# ##################
# f_medatata_log=open( os.path.join(context['temp_directory'],'tmp_6147_meta.mapping.sql'), 'w')
# subprocess.call( [ context['isql_path'], '-x', 'localhost:%(db_connect_string)s' % locals(),'-user', user_name, '-pas', user_password ], stdout=f_medatata_log, stderr=subprocess.STDOUT )
# flush_and_close( f_medatata_log )
#
#
# # Remove global mapping:
# ########################
# f_cleanup_sql = open( os.path.join(context['temp_directory'],'tmp_6147_cleanup.sql'), 'w')
# sql_txt='''
# set bail on;
# -- NB: here we have to connect as "common" SYSDBA (using Srp) rather than Win_SSPI.
# -- Otherwise global mapping can not be deleted:
# -- ############################################
# -- Statement failed, SQLSTATE = 28000
# -- unsuccessful metadata update
# -- -DROP MAPPING TRUSTED_AUTH_C6147 failed
# -- -Unable to perform operation
# -- -System privilege CHANGE_MAPPING_RULES is missing
# -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# -- This I can not explain: why user who did create global mapping can not delete it ???
# -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# connect 'localhost:%(db_connect_string)s' user %(user_name)s password '%(user_password)s';
# drop global mapping trusted_auth_c6147;
# ''' % dict(globals(), **locals())
#
# if PLUGIN_FOR_MAPPING == 'Srp':
# sql_txt += '''
# -- Delete record from rdb$auth_mapping (only when used plugin = 'Srp'):
# drop mapping trusted_auth_c6147;
# '''
#
# sql_txt += '''
# commit;
#
# %(SHOW_MAP_INFO_QUERY)s
# quit;
#
# -- DOES NOT HELP! DATABASE FILE REMAINS OPENED BY FIREBIRD!
# -- ALTER EXTERNAL CONNECTIONS POOL CLEAR ALL; -- !! mandatory otherwise database file will be kept by engine and fbtest will not able to drop it !!
# -- drop database; --> does not raise errot when clear pool but DB file still remains opened !!!
# ''' % dict(globals(), **locals())
#
# f_cleanup_sql.write(sql_txt)
# flush_and_close( f_cleanup_sql )
#
# # DROP MAPPING:
# ###############
# f_cleanup_log = open( os.path.join(context['temp_directory'],'tmp_6147_cleanup.log'), 'w')
# subprocess.call( [ context['isql_path'], "-q", "-i", f_cleanup_sql.name ], stdout=f_cleanup_log, stderr=subprocess.STDOUT )
# flush_and_close( f_cleanup_log )
#
# subprocess.call( [context['gfix_path'], 'localhost:%(db_connect_string)s' % locals(), '-shut', 'single', '-force', '0', '-user', user_name, '-pas', user_password] )
#
# # RESTORE original config:
# ##########################
# shutil.move( dbcbak, dbconf)
#
# with open(f_prepare_log.name, 'r') as f:
# for line in f:
# if line.split():
# print('AFTER_MADE_MAPPING: ' + line)
#
# allowed_patterns = (
# re.compile('MAPPING TRUSTED_AUTH_C6147', re.IGNORECASE)
# ,re.compile('SQLSTATE', re.IGNORECASE)
# ,re.compile('Missing security', re.IGNORECASE)
# ,re.compile('Your user', re.IGNORECASE)
# )
#
# with open(f_medatata_log.name, 'r') as f:
# for line in f:
# match2some = [ p.search(line) for p in allowed_patterns ]
# if max(match2some):
# print('EXTRACTED_METADATA: ' + line)
#
# with open(f_cleanup_log.name, 'r') as f:
# for line in f:
# if line.split():
# print('AFTER_DROP_MAPPING: ' + line)
#
# # CLEANUP:
# ##########
# time.sleep(1)
# f_list=(
# f_prepare_sql
# ,f_prepare_log
# ,f_medatata_log
# ,f_cleanup_sql
# ,f_cleanup_log
# ,tmp_fdb
# )
# cleanup( f_list )
#
#
#
#---