mirror of
https://github.com/FirebirdSQL/firebird-qa.git
synced 2025-01-22 13:33:07 +01:00
137 lines
4.9 KiB
Python
137 lines
4.9 KiB
Python
#coding:utf-8
|
|
|
|
"""
|
|
ID: issue-7979
|
|
ISSUE: https://github.com/FirebirdSQL/firebird/issues/7979
|
|
TITLE: Hang when database with disconnect trigger using MON$ tables is shutting down
|
|
DESCRIPTION:
|
|
NOTES:
|
|
[02.02.2024] pzotov
|
|
### ACHTUNG ###
|
|
Bug could NOT be reproduced on Windows.
|
|
Bug can be reproduced only when appropriate code runs OUTSIDE current firebird-QA framework, i.e. directly from OS.
|
|
Because of that, this test creates temporary .py script which is launched further using subprocess.run( [ sys.executable ...] )
|
|
Confirmed problem on 6.0.0.219: 'gfix -shut full -force 0' hangs.
|
|
Checked on 6.0.0.244.
|
|
|
|
[15.02.2024] pzotov
|
|
Checked on 4.0.5.3059 (commit #a552f1f3), 5.0.1.1340 (commit #f7171b58).
|
|
NOTE: 3.0.123.3731 (dob=15.02.2024) does NOT pass this test.
|
|
|
|
[16.02.2024] pzotov
|
|
Added [temporary] mark for SKIP this test when QA runs agains *fork* of standard FB because it hangs ('disabled_in_forks').
|
|
This mark will be removed after separating QA runs (executing tests against standard FB snapshot on DEDICATED machine).
|
|
|
|
NB-1. QA must use command like: 'pytest -m "not disabled_in_forks" ...' when check *fork* of standard FB.
|
|
NB-2. Unfortunately, nowadays QA runs for standard FB and its fork are performed at the same host.
|
|
Lagging problem exists with [back-]porting of some fixes/features into fork after implementation for the same FB-major version.
|
|
This can cause the whole QA-job to be incompleted and missed report for one of even several days.
|
|
"""
|
|
import sys
|
|
import subprocess
|
|
from pathlib import Path
|
|
import pytest
|
|
from firebird.qa import *
|
|
|
|
init_sql = f"""
|
|
create table logger (dts timestamp default 'now', att_cnt int);
|
|
set term ^;
|
|
execute block as
|
|
begin
|
|
rdb$set_context('USER_SESSION', 'INITIAL_DDL', 1);
|
|
end
|
|
^
|
|
create trigger logger active on disconnect as
|
|
declare c int;
|
|
begin
|
|
if ( rdb$get_context('USER_SESSION', 'INITIAL_DDL') is null ) then
|
|
begin
|
|
select count(*) from mon$attachments where mon$attachment_id = current_connection into :c;
|
|
insert into logger(att_cnt) values(:c);
|
|
end
|
|
end
|
|
^
|
|
set term ;^
|
|
commit;
|
|
"""
|
|
|
|
db = db_factory(init = init_sql)
|
|
act = python_act('db', substitutions = [ ('^((?!(Attributes|ATT_CNT|Records affected)).)*$', ''), ('[ \t]+', ' ') ])
|
|
tmp_run_py = temp_file('tmp_7979_run_external.py')
|
|
tmp_log_py = temp_file('tmp_7979_run_external.log')
|
|
tmp_sql_py = temp_file('tmp_7979_check_result.sql')
|
|
|
|
@pytest.mark.disabled_in_forks
|
|
@pytest.mark.version('>=4.0.5')
|
|
def test_1(act: Action, tmp_run_py: Path, tmp_log_py: Path, tmp_sql_py: Path, capsys):
|
|
if act.platform == 'Windows':
|
|
pytest.skip('Could not reproduce bug on Windows')
|
|
if act.get_server_architecture() != 'SuperServer':
|
|
pytest.skip('Applies only to SuperServer')
|
|
|
|
py_run_ext = ' '.join( [ sys.executable, '-u', f'{str(tmp_run_py)}'] )
|
|
|
|
##########################################################################################
|
|
### G E N E R A T I O N O F T E M P O R A R Y P Y T H O N S C R I P T ###
|
|
##########################################################################################
|
|
py_source = f"""# -*- coding: utf-8 -*-
|
|
# {py_run_ext}
|
|
import os
|
|
import sys
|
|
import argparse as ap
|
|
from pathlib import Path
|
|
import subprocess
|
|
import datetime as py_dt
|
|
|
|
import firebird.driver
|
|
from firebird.driver import *
|
|
|
|
os.environ["ISC_USER"] = '{act.db.user}'
|
|
os.environ["ISC_PASSWORD"] = '{act.db.password}'
|
|
driver_config.fb_client_library.value = r"{act.vars['fbclient']}"
|
|
|
|
bin_isql = r"{act.vars['isql']}"
|
|
bin_gfix = r"{act.vars['gfix']}"
|
|
bin_gstat = r"{act.vars['gstat']}"
|
|
db_conn = r'{act.db.dsn}'
|
|
db_file = r'{act.db.db_path}'
|
|
tmp_sql = r'{str(tmp_sql_py)}'
|
|
|
|
with connect(db_conn) as con:
|
|
#print(f"Trying to run gfix -shut full -force 0 db_conn")
|
|
subprocess.run( [bin_gfix, '-shut', 'full', '-force', '0', db_conn] )
|
|
subprocess.run( [bin_gstat, '-h', db_file] )
|
|
#print(f"Trying to run gfix -online db_conn")
|
|
subprocess.run( [bin_gfix, '-online', db_conn] )
|
|
subprocess.run( [bin_gstat, '-h', db_file] )
|
|
|
|
chk_sql='''
|
|
set list on;
|
|
set count on;
|
|
select att_cnt from logger;
|
|
'''
|
|
with open(tmp_sql, 'w') as f:
|
|
f.write(chk_sql)
|
|
|
|
subprocess.run( [bin_isql, '-q', '-i', tmp_sql, db_conn] )
|
|
"""
|
|
########################################################
|
|
### END OF GENERATION OF TEMPORARY PYTHON SCRIPT ###
|
|
########################################################
|
|
|
|
tmp_run_py.write_text(py_source)
|
|
with open(tmp_log_py, 'w') as f:
|
|
subprocess.run( [ sys.executable, '-u', f'{str(tmp_run_py)}'], stdout = f, stderr = subprocess.STDOUT )
|
|
|
|
with open(tmp_log_py, 'r') as f:
|
|
print(f.read())
|
|
act.expected_stdout = """
|
|
Attributes full shutdown
|
|
Attributes
|
|
ATT_CNT 1
|
|
Records affected: 1
|
|
"""
|
|
act.stdout = capsys.readouterr().out
|
|
assert act.clean_stdout == act.clean_expected_stdout
|
|
act.reset()
|