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

Added/Updated bugs\gh_6790_test.py. Re-implemented. Checked on 5.0.0.623, 4.0.1.2692 - both on Windows and Linux.

This commit is contained in:
zotov 2022-08-18 13:51:02 +03:00
parent 198da5ad4b
commit b366eff138

View File

@ -2,219 +2,95 @@
""" """
ID: issue-6790 ID: issue-6790
ISSUE: 6790 ISSUE: https://github.com/FirebirdSQL/firebird/issues/6790
TITLE: MON$ATTACHMENTS.MON$TIMESTAMP is incorrect when DefaultTimeZone is configured TITLE: MON$ATTACHMENTS.MON$TIMESTAMP is incorrect when DefaultTimeZone is configured with time zone different from the server's default
with time zone different from the server's default
DESCRIPTION: DESCRIPTION:
We make backup of current firebird.conf before changing its parameter DefaultTimeZone to randomly selected value from RDB$TIME_ZONES. Test creates custom DatabaseConfig object for writing in its session_time_zone value that will differ from server.
Then we close current connection and launch child ISQL process that makes *LOCAL* connect to current DB. Query to rdb$time_zones is performed for obtaining random record and assigns it to DefaultTimeZone column of DB config.
ISQL will obtain mon$session_timezone, mon$timestamp and current_timestamp values from mon$attachments.
Then it will extract time zone name from current_timestamp string (by call substring() with specifying starting position = 26).
Values of mon$session_timezone and extracted time zone from current_timestamp must be equals. Then we obtain values of current_timestamp and mon$attachments.mon$timestamp for current connection, and parse them in order to:
Also, difference between mon$timestamp current_timestamp must be no more than 1..2 seconds (see 'MAX_DIFF_SECONDS' variable). * get timezone name for each of these values;
* get timestamp WITHOUT timezone name.
::: NB ::: Result of parsing for these values must meet following conditions:
1. Affect of changed parameter DefaultTimeZone can be seen only if DB is attached using *LOCAL* protocol. 1) both timestamps must belong to the same time zone (this was NOT so before fix);
Attempt to connect using remote protocol will fail: engine returns previous value of DefaultTimeZone. 2) difference between timestamps must not be valuable, usually this must be no more than 1..2 seconds (see 'MAX_DIFF_MS')
One need to wait at least 130 seconds after changing firebird.conf for new value be returned at this case!
The reason of that is 10+60+60 seconds which are needed to fully unload shmem-related structures from memory.
Explanation from Vlad: letter 24.01.2021 18:00, subj: "System audit in FB. Is there some kind of timeout of 130 seconds ?"
(it was discussion about attempts make test for CORE-5993)
See also: http://tracker.firebirdsql.org/browse/CORE-6476
2. FDB driver loads client library only *once* before this test launch and, in turn, this library reads firebird.conf.
For this reason we have to launch separate (child) process two times, which will be forced to load firebird.conf
every launch. This is why subprocess.call(['isql', ...]) is needed here rather than just query DB using cursor of
pre-existing db_conn connection (see routine 'get_local_time').
NOTES:
[22.05.2021]
This test initially had wrong value of min_version = 4.0
Bug was fixed on 4.1.0.2468, build timestamp: 06-may-2021 12:34 thus min_version should be 4.1
After several days this new FB branch was renamed to 5.0.
Because of this, min_version for this test is 5.0
FBTEST: bugs.gh_6790 FBTEST: bugs.gh_6790
NOTES:
[18.08.2022] pzotov
Confirmed problem on WI-V4.0.0.2436: either different time zones or too big time differences can be issued.
Improvement ('add MON$SESSION_TIMEZONE to MON$ATTACHMENTS') commit info:
06-may-2021 15:18
https://github.com/FirebirdSQL/firebird/commit/c8750376bb78e5a588fb269a144bba4dea34ae47
Checked on 5.0.0.623, 4.0.1.2692 - both on Windows and Linux.
""" """
import datetime
from datetime import timedelta
import pytest import pytest
from firebird.qa import * from firebird.qa import *
from firebird.driver import driver_config, connect
MAX_DIFF_MS = 1500
db = db_factory() db = db_factory()
act = python_act('db') act = python_act('db')
expected_stdout = """ @pytest.mark.version('>=4.0')
mon$session_timezone = current_timestamp zone ? => OK, EQUALS. def test_1(act: Action, capsys):
mon$timestamp = current_timestamp ? => OK, EQUALS.
"""
@pytest.mark.skip('FIXME: Not IMPLEMENTED') with act.db.connect() as con:
@pytest.mark.version('>=5.0') with con.cursor() as cur:
def test_1(act: Action): cur.execute('select z.rdb$time_zone_name from rdb$time_zones z order by rand() rows 1')
pytest.fail("Not IMPLEMENTED") RANDOM_TZ = cur.fetchone()[0]
# test_script_1 db_cfg_name = f'tmp_gh_6790'
#--- db_cfg_object = driver_config.register_database(name = db_cfg_name)
#
# import os db_cfg_object.database.value = str(act.db.db_path)
# import shutil db_cfg_object.session_time_zone.value = RANDOM_TZ
# import time
# import datetime sql_chk = f"""
# import subprocess select
# from fdb import services cast(t1 as varchar(255)) as ts1
# ,cast(t2 as varchar(255)) as ts2
# os.environ["ISC_USER"] = user_name from (
# os.environ["ISC_PASSWORD"] = user_password select
# current_timestamp as t1
# db_name = db_conn.database_name ,a.mon$timestamp as t2
# cur =db_conn.cursor() from mon$attachments a
# cur.execute('select z.rdb$time_zone_name from rdb$time_zones z order by rand() rows 1') where a.mon$attachment_id = current_connection
# RANDOM_TZ = cur.fetchone()[0] );
# cur.close() """
# db_conn.close()
# tz_names_set = set()
# MAX_DIFF_SECONDS = 3 time_values = []
# with connect(db_cfg_name) as con:
# #-------------------------------------------- with con.cursor() as cur:
# for r in cur.execute(sql_chk):
# def flush_and_close( file_handle ): for i,col in enumerate(cur.description):
# # https://docs.python.org/2/library/os.html#os.fsync # print((col[0]).ljust(63), r[i])
# # If you're starting with a Python file object f, tz_names_set.add( r[i].split()[-1] ) # '2022-08-18 19:59:48.6860 Pacific/Yap' ==> 'Pacific/Yap'
# # first do f.flush(), and time_values.append(datetime.datetime.strptime(r[i][:23], '%Y-%m-%d %H:%M:%S.%f') )
# # then do os.fsync(f.fileno()), to ensure that all internal buffers associated with f are written to disk.
# global os
# expected_stdout = 'Timestamps difference acceptable.'
# file_handle.flush() time_diff_ms = (max(time_values) - min(time_values)).total_seconds() * 1000
# if file_handle.mode not in ('r', 'rb') and file_handle.name != os.devnull:
# # otherwise: "OSError: [Errno 9] Bad file descriptor"! if time_diff_ms <= MAX_DIFF_MS and len(tz_names_set) ==1:
# os.fsync(file_handle.fileno()) print(expected_stdout)
# file_handle.close() else:
# print(f'UNEXPECTED: detected either diff time zones or too significant difference between timestamps.')
# #-------------------------------------------- print('1. Check tz_names_set:')
# for p in tz_names_set:
# def cleanup( f_names_list ): print(p)
# global os print(f'2. Check time_values (difference: {time_diff_ms} ms)')
# for f in f_names_list: for p in time_values:
# if type(f) == file: print(p)
# del_name = f.name
# elif type(f) == str:
# del_name = f act.expected_stdout = expected_stdout
# else: act.stdout = capsys.readouterr().out
# print('Unrecognized type of element:', f, ' - can not be treated as file.') assert act.clean_stdout == act.clean_expected_stdout
# del_name = None
#
# if del_name and os.path.isfile( del_name ):
# os.remove( del_name )
#
# #--------------------------------------------
#
# def get_local_time( fb_home, db_name ):
#
# global flush_and_close
# global subprocess
# global cleanup
#
# sql_chk='select substring( cast(cast(current_time as time) as varchar(13)) from 1 for 8) from rdb$database'
#
# f_connect_sql = open( os.path.join(context['temp_directory'],'tmp_6396_check.sql'), 'w')
# f_connect_sql.write('set heading off; ' + sql_chk + ';' )
# flush_and_close( f_connect_sql )
#
# f_connect_log=open( os.path.join(context['temp_directory'],'tmp_6396_check.log'), 'w')
# subprocess.call( [ context['isql_path'], db_name, "-i", f_connect_sql.name ], stdout=f_connect_log, stderr=subprocess.STDOUT )
# flush_and_close( f_connect_log )
#
# changed_time = '00:00:00'
# with open(f_connect_log.name,'r') as f:
# for line in f:
# if line.split():
# changed_time = line.strip()
#
# cleanup( [x.name for x in (f_connect_sql, f_connect_log)] )
# return changed_time
#
# #---------------------------------------------
#
# svc = services.connect(host='localhost', user=user_name, password=user_password)
# fb_home = svc.get_home_directory()
# svc.close()
#
# dts = datetime.datetime.now().strftime("%y%m%d_%H%M%S")
#
# fbconf_cur = os.path.join(fb_home, 'firebird.conf')
# fbconf_bak = os.path.join(context['temp_directory'], 'firebird_'+dts+'.bak')
#
# shutil.copy2( fbconf_cur, fbconf_bak )
#
# f_fbconf=open( fbconf_cur, 'r')
# fbconf_content=f_fbconf.readlines()
# flush_and_close( f_fbconf )
#
# for i,s in enumerate( fbconf_content ):
# line = s.lower().lstrip()
# if line.startswith( 'DefaultTimeZone'.lower() ):
# fbconf_content[i] = '# [temply commented] ' + s
#
# text2app='''
# ### TEMPORARY CHANGED BY FBTEST FRAMEWORK ###
# DefaultTimeZone = %(RANDOM_TZ)s
# ##############################################
# ''' % locals()
#
# f_fbconf=open( fbconf_cur, 'w')
# f_fbconf.writelines( fbconf_content + [ '\\n' + x for x in text2app.split('\\n') ] )
# flush_and_close( f_fbconf )
# #..........................................
#
#
# sql_chk='''
# set list on;
# select
# iif( t.mon_session_timezone = t.curent_timestamp_zone, 'OK, EQUALS.', 'POOR: mon$session_timezone = "' || trim(coalesce(mon_session_timezone, '[null]')) || '", curent_timestamp_zone = "' || trim(coalesce(curent_timestamp_zone, '[null]')) || '"' ) as "mon$session_timezone = current_timestamp zone ? =>"
# ,iif( abs(t.timestamp_diff_seconds) < t.max_diff_seconds, 'OK, EQUALS.', 'POOR: mon$timestamp differs from current_timestamp for more than ' || t.max_diff_seconds ||' seconds.' ) as "mon$timestamp = current_timestamp ? =>"
# from (
# select
# m.mon$session_timezone as mon_session_timezone
# ,substring(cast(current_timestamp as varchar(255)) from 26) as curent_timestamp_zone
# ,datediff(second from current_timestamp to m.mon$timestamp) as timestamp_diff_seconds
# ,%(MAX_DIFF_SECONDS)s as max_diff_seconds
# from mon$attachments m
# where m.mon$attachment_id=current_connection
# ) t;
# ''' % locals()
#
# f_connect_sql = open( os.path.join(context['temp_directory'],'tmp_6790_check.sql'), 'w')
# f_connect_sql.write('set heading off; ' + sql_chk + ';' )
# flush_and_close( f_connect_sql )
#
# f_connect_log=open( os.path.join(context['temp_directory'],'tmp_6790_check.log'), 'w')
#
# ###############
# ### ACHTUNG ###
# ###############
# # LOCAL protocol must be used here!
# # Attempt to connect using remote protocol will fail: engine returns previous value of DefaultTimeZone.
# # One need to wait at least 130 seconds after changing firebird.conf for new value be returned at this case!
# # The reason of that is 10+60+60 seconds which are needed to fully unload shmem-related structures from memory.
# # Explanation from Vlad: letter 24.01.2021 18:00, subj: "System audit in FB. Is there some kind of timeout of 130 seconds ?"
# # (it was discussion about attempts make test for CORE-5993)
# # See also: http://tracker.firebirdsql.org/browse/CORE-6476
#
# subprocess.call( [ context['isql_path'], db_name, "-i", f_connect_sql.name ], stdout=f_connect_log, stderr=subprocess.STDOUT )
#
# flush_and_close( f_connect_log )
#
# # RESTORE previous content of firebird.conf. This must be done BEFORE drop mapping!
# shutil.move( fbconf_bak, fbconf_cur )
#
# with open(f_connect_log.name,'r') as f:
# for line in f:
# if line.split():
# print(line)
#
# # CLEANUP:
# ##########
# time.sleep(1)
# cleanup( (f_connect_sql, f_connect_log,) )
#
#---