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

131 lines
4.4 KiB
Python

#coding:utf-8
"""
ID: issue-5015
ISSUE: 5015
TITLE: Implement ability to validate tables and indices online (without exclusive access to database)
DESCRIPTION:
JIRA: CORE-4707
FBTEST: bugs.core_4707
"""
import pytest
import subprocess
import time
from pathlib import Path
from firebird.qa import *
init_script = """
set term ^;
execute block as
begin
execute statement 'drop sequence g';
when any do begin end
end^
set term ;^
commit;
create sequence g;
commit;
recreate table test1(id int, s varchar(1000));
recreate table test2(id int primary key using index test2_pk, s varchar(1000), t computed by (s) );
recreate table test3(id int);
commit;
insert into test1(id, s) select gen_id(g,1), rpad('', 1000, gen_id(g,0) ) from rdb$types rows 100;
insert into test2(id, s) select id, s from test1;
commit;
create index test2_s on test2(s);
create index test2_c on test2 computed by(s);
create index test2_t on test2 computed by(t);
commit;
"""
db = db_factory(init=init_script)
act = python_act('db', substitutions=[('[\\d]{2}:[\\d]{2}:[\\d]{2}.[\\d]{2}', ''),
('Relation [\\d]{3,4}', 'Relation')])
expected_stdout = """
ISQL_MSG Starting EB with infinite pause.
08:37:01.14 Validation started
08:37:01.15 Relation 128 (TEST1)
08:37:02.15 Acquire relation lock failed
08:37:02.15 Relation 128 (TEST1) : 1 ERRORS found
08:37:02.15 Relation 129 (TEST2)
08:37:02.15 process pointer page 0 of 1
08:37:02.15 Index 1 (TEST2_PK)
08:37:02.15 Index 2 (TEST2_S)
08:37:02.15 Index 3 (TEST2_C)
08:37:02.15 Index 4 (TEST2_T)
08:37:02.17 Relation 129 (TEST2) is ok
08:37:02.17 Relation 130 (TEST3)
08:37:03.17 Acquire relation lock failed
08:37:03.17 Relation 130 (TEST3) : 1 ERRORS found
08:37:03.17 Validation finished
"""
hang_script_file = temp_file('hang_script.sql')
hang_output = temp_file('hang_script.out')
@pytest.mark.es_eds
@pytest.mark.version('>=2.5.5')
def test_1(act: Action, hang_script_file: Path, hang_output: Path, capsys, request):
# Fializer for FB4
def drop_connections():
with act.db.connect() as con4cleanup:
con4cleanup.execute_immediate('delete from mon$attachments where mon$attachment_id != current_connection')
con4cleanup.commit()
request.addfinalizer(drop_connections)
# Following script will hang for sevral seconds (see 'lock timeout' argument - and this will serve as pause
# during which we can launch fbsvcmgr to validate database:
hang_script_file.write_text(f"""
set term ^;
execute block as
begin
execute statement 'drop role tmp$r4707';
when any do begin end
end ^
set term ;^
commit;
set transaction wait;
delete from test1;
insert into test3(id) values(1);
set list on;
select 'Starting EB with infinite pause.' as isql_msg from rdb$database;
set term ^;
execute block as
begin
execute statement 'update test1 set id=-id'
on external 'localhost:' || rdb$get_context('SYSTEM','DB_NAME')
as user '{act.db.user}' password '{act.db.password}'
role 'TMP$R4707' -- this will force to create new attachment, and its Tx will be paused on INFINITE time.
;
when any do begin end
end ^
set term ;^
select 'EB with pause finished.' as msg_2 from rdb$database;
""")
# Make asynchronous call of ISQL which will stay several seconds in pause due to row-level lock
with open(hang_output, mode='w') as hang_out:
p_hang_sql = subprocess.Popen([act.vars['isql'], '-i', str(hang_script_file),
'-user', act.db.user,
'-password', act.db.password, act.db.dsn],
stdout=hang_out, stderr=subprocess.STDOUT)
try:
time.sleep(2)
# Make SYNC. call of fbsvcmgr in order to validate database which has locks on some relations
act.svcmgr(switches=['action_validate', 'dbname', str(act.db.db_path),
'val_lock_timeout', '1'])
finally:
p_hang_sql.terminate()
#
print(hang_output.read_text())
print(act.stdout)
act.expected_stdout = expected_stdout
act.stdout = capsys.readouterr().out
assert act.clean_stdout == act.clean_expected_stdout