mirror of
https://github.com/FirebirdSQL/firebird-qa.git
synced 2025-02-02 02:40:42 +01:00
Set '@pytest.mark.es_eds' to tests which relate to ES/EDS mechanism.
This commit is contained in:
parent
71b430dcd5
commit
188f82dba7
@ -100,7 +100,7 @@ expected_stderr = """
|
|||||||
-At block line: 3, col: 7
|
-At block line: 3, col: 7
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=3')
|
@pytest.mark.version('>=3')
|
||||||
def test_1(act: Action, cvc_user: User, for_role: Role, for_cvc_role: Role):
|
def test_1(act: Action, cvc_user: User, for_role: Role, for_cvc_role: Role):
|
||||||
act.expected_stdout = expected_stdout
|
act.expected_stdout = expected_stdout
|
||||||
|
@ -146,6 +146,7 @@ expected_stdout = """
|
|||||||
USING_INDEX 1
|
USING_INDEX 1
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=3.0')
|
@pytest.mark.version('>=3.0')
|
||||||
def test_1(act: Action):
|
def test_1(act: Action):
|
||||||
act.expected_stdout = expected_stdout
|
act.expected_stdout = expected_stdout
|
||||||
|
@ -120,6 +120,7 @@ expected_stdout = """
|
|||||||
PID 1
|
PID 1
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=3')
|
@pytest.mark.version('>=3')
|
||||||
def test_1(act: Action):
|
def test_1(act: Action):
|
||||||
act.expected_stdout = expected_stdout
|
act.expected_stdout = expected_stdout
|
||||||
|
@ -209,6 +209,7 @@ expected_stderr_2 = """
|
|||||||
-At block line
|
-At block line
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=4.0')
|
@pytest.mark.version('>=4.0')
|
||||||
def test_2(act_2: Action):
|
def test_2(act_2: Action):
|
||||||
act_2.expected_stderr = expected_stderr_2
|
act_2.expected_stderr = expected_stderr_2
|
||||||
|
@ -119,6 +119,7 @@ expected_stdout = """
|
|||||||
ATTACHES_I_CAN_SEE 11
|
ATTACHES_I_CAN_SEE 11
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=3')
|
@pytest.mark.version('>=3')
|
||||||
def test_1(act: Action):
|
def test_1(act: Action):
|
||||||
act.expected_stdout = expected_stdout
|
act.expected_stdout = expected_stdout
|
||||||
|
@ -77,6 +77,7 @@ expected_stderr = """
|
|||||||
-At block line: 11, col: 9
|
-At block line: 11, col: 9
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=3.0')
|
@pytest.mark.version('>=3.0')
|
||||||
def test_1(act: Action):
|
def test_1(act: Action):
|
||||||
act.expected_stdout = expected_stdout
|
act.expected_stdout = expected_stdout
|
||||||
|
@ -110,6 +110,7 @@ expected_stdout = """
|
|||||||
DISTINCT_STATEMENT_ID_THEY_SAW 1
|
DISTINCT_STATEMENT_ID_THEY_SAW 1
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=3')
|
@pytest.mark.version('>=3')
|
||||||
def test_1(act: Action):
|
def test_1(act: Action):
|
||||||
act.expected_stdout = expected_stdout
|
act.expected_stdout = expected_stdout
|
||||||
|
@ -63,6 +63,7 @@ select '-- shutdown me now --' from rdb$database;
|
|||||||
|
|
||||||
tmp_script = temp_file('work_script.sql')
|
tmp_script = temp_file('work_script.sql')
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=3')
|
@pytest.mark.version('>=3')
|
||||||
def test_1(act: Action, tmp_script: Path):
|
def test_1(act: Action, tmp_script: Path):
|
||||||
tmp_script.write_text(test_script)
|
tmp_script.write_text(test_script)
|
||||||
|
@ -85,6 +85,7 @@ expected_stderr = """
|
|||||||
-At block line: 5, col: 5
|
-At block line: 5, col: 5
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=3')
|
@pytest.mark.version('>=3')
|
||||||
def test_1(act: Action):
|
def test_1(act: Action):
|
||||||
act.expected_stderr = expected_stderr
|
act.expected_stderr = expected_stderr
|
||||||
|
@ -152,6 +152,7 @@ expected_stdout = """
|
|||||||
MEASURE_RESULT WINS >= 3.8x
|
MEASURE_RESULT WINS >= 3.8x
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=3.0')
|
@pytest.mark.version('>=3.0')
|
||||||
def test_1(act: Action):
|
def test_1(act: Action):
|
||||||
act.expected_stdout = expected_stdout
|
act.expected_stdout = expected_stdout
|
||||||
|
@ -252,6 +252,7 @@ Statement failed, SQLSTATE = HY000
|
|||||||
record not found for user: TMP$C3100B
|
record not found for user: TMP$C3100B
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=3.0')
|
@pytest.mark.version('>=3.0')
|
||||||
def test_1(act: Action):
|
def test_1(act: Action):
|
||||||
act.expected_stdout = expected_stdout
|
act.expected_stdout = expected_stdout
|
||||||
|
@ -99,6 +99,7 @@ expected_stderr = """
|
|||||||
-At block line: 4, col: 7
|
-At block line: 4, col: 7
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=3.0')
|
@pytest.mark.version('>=3.0')
|
||||||
def test_1(act: Action):
|
def test_1(act: Action):
|
||||||
act.expected_stdout = expected_stdout
|
act.expected_stdout = expected_stdout
|
||||||
|
@ -80,6 +80,7 @@ expected_stderr = """
|
|||||||
-At block line: 3, col: 9
|
-At block line: 3, col: 9
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=3')
|
@pytest.mark.version('>=3')
|
||||||
def test_1(act: Action):
|
def test_1(act: Action):
|
||||||
act.expected_stdout = expected_stdout
|
act.expected_stdout = expected_stdout
|
||||||
|
@ -143,6 +143,7 @@ expected_stderr = """
|
|||||||
335544878 : concurrent transaction number is 806
|
335544878 : concurrent transaction number is 806
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=3.0')
|
@pytest.mark.version('>=3.0')
|
||||||
def test_1(act: Action, user_1_ro: User, user_1_ud: User):
|
def test_1(act: Action, user_1_ro: User, user_1_ud: User):
|
||||||
act.expected_stdout = expected_stdout
|
act.expected_stdout = expected_stdout
|
||||||
|
@ -117,6 +117,7 @@ expected_stdout = """
|
|||||||
WHAT_I_SEE 789654123
|
WHAT_I_SEE 789654123
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=3')
|
@pytest.mark.version('>=3')
|
||||||
def test_1(act: Action):
|
def test_1(act: Action):
|
||||||
act.expected_stdout = expected_stdout
|
act.expected_stdout = expected_stdout
|
||||||
|
@ -142,6 +142,7 @@ expected_stdout = """
|
|||||||
MINE_F01 300
|
MINE_F01 300
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=3.0')
|
@pytest.mark.version('>=3.0')
|
||||||
def test_1(act: Action, tmp_user: User):
|
def test_1(act: Action, tmp_user: User):
|
||||||
act.expected_stdout = expected_stdout
|
act.expected_stdout = expected_stdout
|
||||||
|
@ -91,6 +91,7 @@ expected_stdout = """
|
|||||||
LNAME Zeppelin
|
LNAME Zeppelin
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=3.0')
|
@pytest.mark.version('>=3.0')
|
||||||
def test_1(act: Action, tmp_user: User):
|
def test_1(act: Action, tmp_user: User):
|
||||||
act.expected_stdout = expected_stdout
|
act.expected_stdout = expected_stdout
|
||||||
|
@ -73,6 +73,7 @@ expected_stdout = """
|
|||||||
CNT 0
|
CNT 0
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=3.0')
|
@pytest.mark.version('>=3.0')
|
||||||
def test_1(act: Action):
|
def test_1(act: Action):
|
||||||
act.expected_stdout = expected_stdout
|
act.expected_stdout = expected_stdout
|
||||||
|
@ -91,6 +91,7 @@ expected_stdout = """
|
|||||||
STR_SIZE 36
|
STR_SIZE 36
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=3')
|
@pytest.mark.version('>=3')
|
||||||
def test_1(act: Action):
|
def test_1(act: Action):
|
||||||
act.expected_stdout = expected_stdout
|
act.expected_stdout = expected_stdout
|
||||||
|
@ -68,6 +68,7 @@ expected_stdout = """
|
|||||||
hang_script_file = temp_file('hang_script.sql')
|
hang_script_file = temp_file('hang_script.sql')
|
||||||
hang_output = temp_file('hang_script.out')
|
hang_output = temp_file('hang_script.out')
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=2.5.5')
|
@pytest.mark.version('>=2.5.5')
|
||||||
def test_1(act: Action, hang_script_file: Path, hang_output: Path, capsys, request):
|
def test_1(act: Action, hang_script_file: Path, hang_output: Path, capsys, request):
|
||||||
# Fializer for FB4
|
# Fializer for FB4
|
||||||
|
@ -35,6 +35,7 @@ substitutions=[ ('RUNNING_STT_ID[ ]+[0-9]+', 'RUNNING_STT_ID'),
|
|||||||
|
|
||||||
act = python_act('db', substitutions = substitutions)
|
act = python_act('db', substitutions = substitutions)
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=3')
|
@pytest.mark.version('>=3')
|
||||||
def test_1(act: Action):
|
def test_1(act: Action):
|
||||||
|
|
||||||
|
@ -73,6 +73,7 @@ expected_stdout = """
|
|||||||
WHOAMI_SRP TMP$C5225
|
WHOAMI_SRP TMP$C5225
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=3.0.1')
|
@pytest.mark.version('>=3.0.1')
|
||||||
def test_1(act: Action, user_srp: User, user_leg: User):
|
def test_1(act: Action, user_srp: User, user_leg: User):
|
||||||
act.expected_stdout = expected_stdout
|
act.expected_stdout = expected_stdout
|
||||||
|
@ -30,6 +30,7 @@ expected_stdout = """
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
@pytest.mark.skip("FIXME: see notes")
|
@pytest.mark.skip("FIXME: see notes")
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=3.0.1')
|
@pytest.mark.version('>=3.0.1')
|
||||||
def test_1(act: Action):
|
def test_1(act: Action):
|
||||||
sql_chk = f"""
|
sql_chk = f"""
|
||||||
|
@ -185,6 +185,7 @@ expected_stderr = """
|
|||||||
-Attachment level timeout expired.
|
-Attachment level timeout expired.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=4.0')
|
@pytest.mark.version('>=4.0')
|
||||||
def test_1(act: Action):
|
def test_1(act: Action):
|
||||||
act.expected_stdout = expected_stdout
|
act.expected_stdout = expected_stdout
|
||||||
|
@ -87,6 +87,7 @@ expected_stdout = """
|
|||||||
GDS_ON_SELECT_WITH_LOCK 335544336
|
GDS_ON_SELECT_WITH_LOCK 335544336
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=3.0.3')
|
@pytest.mark.version('>=3.0.3')
|
||||||
def test_1(act: Action):
|
def test_1(act: Action):
|
||||||
act.expected_stdout = expected_stdout
|
act.expected_stdout = expected_stdout
|
||||||
|
@ -40,6 +40,7 @@ expected_stdout = """
|
|||||||
|
|
||||||
eds_script = temp_file('eds_script.sql')
|
eds_script = temp_file('eds_script.sql')
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=3.0.3')
|
@pytest.mark.version('>=3.0.3')
|
||||||
def test_1(act: Action, eds_script: Path):
|
def test_1(act: Action, eds_script: Path):
|
||||||
eds_sql = f"""
|
eds_sql = f"""
|
||||||
|
@ -152,6 +152,7 @@ hang_stdout = temp_file('hang_script.out')
|
|||||||
hang_stderr = temp_file('hang_script.err')
|
hang_stderr = temp_file('hang_script.err')
|
||||||
|
|
||||||
@pytest.mark.skipif(platform.system() != 'Windows', reason='FIXME: see notes')
|
@pytest.mark.skipif(platform.system() != 'Windows', reason='FIXME: see notes')
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=3.0.3')
|
@pytest.mark.version('>=3.0.3')
|
||||||
def test_1(act: Action, hang_script: Path, hang_stdout: Path, hang_stderr: Path,
|
def test_1(act: Action, hang_script: Path, hang_stdout: Path, hang_stderr: Path,
|
||||||
capsys):
|
capsys):
|
||||||
|
@ -44,6 +44,7 @@ eds_output = temp_file('eds_script.out')
|
|||||||
new_diff_file = temp_file('_new_diff_5704.tmp')
|
new_diff_file = temp_file('_new_diff_5704.tmp')
|
||||||
new_main_file = temp_file('new_main_5704.tmp')
|
new_main_file = temp_file('new_main_5704.tmp')
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=3.0.3')
|
@pytest.mark.version('>=3.0.3')
|
||||||
def test_1(act: Action, eds_script: Path, eds_output: Path, new_diff_file: Path,
|
def test_1(act: Action, eds_script: Path, eds_output: Path, new_diff_file: Path,
|
||||||
new_main_file: Path):
|
new_main_file: Path):
|
||||||
|
@ -99,6 +99,7 @@ expected_stdout = """
|
|||||||
WHAT_PROTOCOL_IM_USING <null>
|
WHAT_PROTOCOL_IM_USING <null>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=3.0.4')
|
@pytest.mark.version('>=3.0.4')
|
||||||
def test_1(act: Action, tmp_user, tmp_role):
|
def test_1(act: Action, tmp_user, tmp_role):
|
||||||
act.expected_stdout = expected_stdout
|
act.expected_stdout = expected_stdout
|
||||||
|
@ -85,6 +85,7 @@ expected_stdout = """
|
|||||||
WHATS_MY_ROLE WORKER
|
WHATS_MY_ROLE WORKER
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=3.0')
|
@pytest.mark.version('>=3.0')
|
||||||
def test_1(act: Action, user_foo, user_bar):
|
def test_1(act: Action, user_foo, user_bar):
|
||||||
act.expected_stdout = expected_stdout
|
act.expected_stdout = expected_stdout
|
||||||
|
@ -165,6 +165,7 @@ expected_stdout = """
|
|||||||
DUP_CNT 5
|
DUP_CNT 5
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=4.0')
|
@pytest.mark.version('>=4.0')
|
||||||
def test_1(act: Action):
|
def test_1(act: Action):
|
||||||
if int(act.get_config('ExtConnPoolSize')) < 6 or int(act.get_config('ExtConnPoolLifeTime')) < 10:
|
if int(act.get_config('ExtConnPoolSize')) < 6 or int(act.get_config('ExtConnPoolLifeTime')) < 10:
|
||||||
|
@ -105,7 +105,7 @@ def init_main_db(act: Action, eds_user: User):
|
|||||||
"""
|
"""
|
||||||
act.isql(switches=[], input=ddl_script)
|
act.isql(switches=[], input=ddl_script)
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=4.0')
|
@pytest.mark.version('>=4.0')
|
||||||
def test_1(act: Action, db_a: Database, db_b: Database, db_c: Database,
|
def test_1(act: Action, db_a: Database, db_b: Database, db_c: Database,
|
||||||
db_d: Database, eds_user: User, capsys):
|
db_d: Database, eds_user: User, capsys):
|
||||||
|
@ -78,6 +78,7 @@ expected_stdout = """
|
|||||||
Records affected: 0
|
Records affected: 0
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=4.0.1')
|
@pytest.mark.version('>=4.0.1')
|
||||||
def test_1(act: Action):
|
def test_1(act: Action):
|
||||||
act.expected_stdout = expected_stdout
|
act.expected_stdout = expected_stdout
|
||||||
|
@ -448,6 +448,7 @@ expected_stdout = f"""
|
|||||||
ID=10
|
ID=10
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=5.0')
|
@pytest.mark.version('>=5.0')
|
||||||
def test_1(act: Action, capsys):
|
def test_1(act: Action, capsys):
|
||||||
|
|
||||||
|
419
tests/bugs/gh_7917_test-obj-in-use-on-drop-db.py
Normal file
419
tests/bugs/gh_7917_test-obj-in-use-on-drop-db.py
Normal file
@ -0,0 +1,419 @@
|
|||||||
|
#coding:utf-8
|
||||||
|
|
||||||
|
"""
|
||||||
|
ID: issue-7917
|
||||||
|
ISSUE: https://github.com/FirebirdSQL/firebird/issues/7917
|
||||||
|
TITLE: Hang in a case of error when sweep thread is attaching to database
|
||||||
|
DESCRIPTION:
|
||||||
|
Test uses preliminary created alias with KeyHolderPlugin that points to special configuration with name 'KH2'.
|
||||||
|
This configuration makes crypt plugin accept key ONLY from client app (in contrary to some other encryption-related tests).
|
||||||
|
DB-level triggers (ON CONNECT, ON DISCONNECT) are created for logging appropriate events (see table 'att_log').
|
||||||
|
Then we run special SQL that uses autonomous transactions and ES/EDS.
|
||||||
|
This script will hang because of update-conflict after some number of transactions (see TX_NUMBER_BEFORE_HANG).
|
||||||
|
We run this script asynchronously, then reduce sweep interval to value SWP_INTERVAL_TO_CHECK that is less than TX_NUMBER_BEFORE_HANG,
|
||||||
|
change DB state to full shutdown and return it online.
|
||||||
|
At this point any connection to DB will fire AUTO SWEEP (normally this can be seen in firebird.log as 'Sweep is started by SWEEPER').
|
||||||
|
We run ISQL that queries 'att_log' table and causes AUTO SWEEP. That ISQL has to normally detach from DB and we must see its results.
|
||||||
|
NOTES:
|
||||||
|
[28.12.2023] pzotov
|
||||||
|
1. To make crypt plugin accept key only from client app, $FB_HOME/plugins.conf must contain following lines:
|
||||||
|
==================
|
||||||
|
Plugin = KH2 {
|
||||||
|
Module = $(dir_plugins)/fbSampleKeyHolder
|
||||||
|
RegisterName = fbSampleKeyHolder
|
||||||
|
Config = KH2
|
||||||
|
}
|
||||||
|
Config = KH2 {
|
||||||
|
Auto = false
|
||||||
|
}
|
||||||
|
==================
|
||||||
|
QA-scenario (.bat and .sh) must add in advance content of $QA_ROOT/files/qa-plugins-supplement.conf to $FB_HOME/plugins.conf.
|
||||||
|
|
||||||
|
2. Demo-plugin (fbSampleKeyHolder) can transfer key over network only for default key which has no-name.
|
||||||
|
Because of this, command 'alter database encrypt with <plugin>' has no '... key <key>' tail.
|
||||||
|
See letter from Alex, 15.12.2023 16:16
|
||||||
|
|
||||||
|
3. In case of regression caused by that bug, we have to be ready that FB will hang on this test!
|
||||||
|
|
||||||
|
Great thanks to Alex for suggestions (discussion started 13.12.2023 13:18).
|
||||||
|
|
||||||
|
Confirmed bug on 6.0.0.173.
|
||||||
|
Checked on 6.0.0.175, 5.0.0.1305, 4.0.5.3049 - but currenlyt only SuperServer works fine.
|
||||||
|
Classic has the same problem. Sent report to Alex, 28.12.2023 13:10.
|
||||||
|
|
||||||
|
On 3.0.12.33726 error raises:
|
||||||
|
unsuccessful metadata update / -ALTER DATABASE failed / -Missing correct crypt key / -Plugin fbSampleDbCrypt: / -Crypt key not set
|
||||||
|
This problem not [yet] investogated.
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import datetime as py_dt
|
||||||
|
import subprocess
|
||||||
|
import locale
|
||||||
|
import re
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from firebird.qa import *
|
||||||
|
from firebird.driver import DatabaseError
|
||||||
|
|
||||||
|
REQUIRED_ALIAS = 'tmp_gh_7917_alias'
|
||||||
|
|
||||||
|
###########################
|
||||||
|
### S E T T I N G S ###
|
||||||
|
###########################
|
||||||
|
|
||||||
|
# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings
|
||||||
|
# from act.files_dir/'test_config.ini':
|
||||||
|
enc_settings = QA_GLOBALS['encryption']
|
||||||
|
|
||||||
|
# ACHTUNG: this must be carefully tuned on every new host:
|
||||||
|
#
|
||||||
|
MAX_WAITING_ENCR_FINISH = int(enc_settings['MAX_WAIT_FOR_ENCR_FINISH_WIN' if os.name == 'nt' else 'MAX_WAIT_FOR_ENCR_FINISH_NIX'])
|
||||||
|
assert MAX_WAITING_ENCR_FINISH > 0
|
||||||
|
|
||||||
|
ENCRYPTION_PLUGIN = enc_settings['encryption_plugin'] # fbSampleDbCrypt
|
||||||
|
ENCRYPTION_KEY = enc_settings['encryption_key'] # Red
|
||||||
|
|
||||||
|
SWP_INTERVAL_TO_CHECK = 100
|
||||||
|
TX_NUMBER_BEFORE_HANG = SWP_INTERVAL_TO_CHECK + 10
|
||||||
|
|
||||||
|
MAX_WAIT_FOR_ISQL_TERMINATE=11
|
||||||
|
|
||||||
|
db = db_factory(filename = '#' + REQUIRED_ALIAS, do_not_drop = True)
|
||||||
|
|
||||||
|
act = python_act('db', substitutions = [('^((?!(ISQL|Attributes)).)*$', ''), ('[ \t]+', ' '), ('TCPv(4|6)$', 'TCP')])
|
||||||
|
#act = python_act('db')
|
||||||
|
|
||||||
|
tmp_sql_file = temp_file('tmp_7917.sql')
|
||||||
|
tmp_log_file = temp_file('tmp_7917.log')
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
def run_encr_decr(act: Action, mode, max_wait_encr_thread_finish, capsys):
|
||||||
|
if mode == 'encrypt':
|
||||||
|
# See letter from Alex, 15.12.2023 16:16 demo-plugin can not transfer named key over network.
|
||||||
|
# Because of that, we have to use following command WITHOUT adding 'key "{ENCRYPTION_KEY}"':
|
||||||
|
# ::: NB ::: One need to be sure that $FB_HOME/plugins.conf contains following lines:
|
||||||
|
# Plugin = KH2 {
|
||||||
|
# Module = $(dir_plugins)/fbSampleKeyHolder
|
||||||
|
# RegisterName = fbSampleKeyHolder
|
||||||
|
# Config = KH2
|
||||||
|
# }
|
||||||
|
# Config = KH2 {
|
||||||
|
# Auto = false
|
||||||
|
# }
|
||||||
|
# Otherwise error will raise:
|
||||||
|
# unsuccessful metadata update
|
||||||
|
# -ALTER DATABASE failed
|
||||||
|
# -Missing database encryption key for your attachment
|
||||||
|
# -Plugin fbSampleDbCrypt:
|
||||||
|
# -Crypt key not set
|
||||||
|
#
|
||||||
|
alter_db_sttm = f'alter database encrypt with "{ENCRYPTION_PLUGIN}"'
|
||||||
|
wait_for_state = 'Database encrypted'
|
||||||
|
elif mode == 'decrypt':
|
||||||
|
alter_db_sttm = 'alter database decrypt'
|
||||||
|
wait_for_state = 'Database not encrypted'
|
||||||
|
|
||||||
|
|
||||||
|
e_thread_started = False
|
||||||
|
e_thread_finished = False
|
||||||
|
with act.db.connect() as con:
|
||||||
|
|
||||||
|
t1=py_dt.datetime.now()
|
||||||
|
d1 = t1-t1
|
||||||
|
try:
|
||||||
|
con.execute_immediate(alter_db_sttm)
|
||||||
|
con.commit()
|
||||||
|
e_thread_started = True
|
||||||
|
except DatabaseError as e:
|
||||||
|
print( e.__str__() )
|
||||||
|
|
||||||
|
while e_thread_started:
|
||||||
|
t2=py_dt.datetime.now()
|
||||||
|
d1=t2-t1
|
||||||
|
if d1.seconds*1000 + d1.microseconds//1000 > max_wait_encr_thread_finish:
|
||||||
|
print(f'TIMEOUT EXPIRATION. Mode="{mode}" took {d1.seconds*1000 + d1.microseconds//1000} ms which exceeds limit = {max_wait_encr_thread_finish} ms.')
|
||||||
|
break
|
||||||
|
|
||||||
|
# Possible output:
|
||||||
|
# Database [not] encrypted
|
||||||
|
# Database encrypted, crypt thread not complete
|
||||||
|
act.isql(switches=['-q'], input = 'show database;', combine_output = True)
|
||||||
|
if wait_for_state in act.stdout:
|
||||||
|
if 'not complete' in act.stdout:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
e_thread_finished = True
|
||||||
|
break
|
||||||
|
act.reset()
|
||||||
|
|
||||||
|
act.expected_stdout = ''
|
||||||
|
act.stdout = capsys.readouterr().out
|
||||||
|
assert act.clean_stdout == act.clean_expected_stdout
|
||||||
|
act.reset()
|
||||||
|
|
||||||
|
assert e_thread_finished
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
|
@pytest.mark.encryption
|
||||||
|
@pytest.mark.version('>=4.0.5')
|
||||||
|
@pytest.mark.platform('Windows')
|
||||||
|
def test_1(act: Action, tmp_sql_file: Path, tmp_log_file: Path, capsys):
|
||||||
|
|
||||||
|
'''
|
||||||
|
with act.db.connect() as con:
|
||||||
|
if act.vars['server-arch'] == 'SuperServer':
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
pytest.skip("Currently fixed only for SuperServer. Temporary SKIPPED.")
|
||||||
|
'''
|
||||||
|
|
||||||
|
# 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_7598_alias = $(dir_sampleDb)/qa/tmp_gh_7598.fdb
|
||||||
|
# - then we extract filename: 'tmp_gh_7598.fdb' (see below):
|
||||||
|
fname_in_dbconf = Path(line.split('=')[1].strip()).name
|
||||||
|
break
|
||||||
|
|
||||||
|
# if 'fname_in_dbconf' remains undefined here then propably REQUIRED_ALIAS not equals to specified in the databases.conf!
|
||||||
|
#
|
||||||
|
assert fname_in_dbconf
|
||||||
|
|
||||||
|
#----------------------------------------------------------------
|
||||||
|
|
||||||
|
run_encr_decr(act, 'encrypt', MAX_WAITING_ENCR_FINISH, capsys)
|
||||||
|
|
||||||
|
test_script = f"""
|
||||||
|
set bail on;
|
||||||
|
create table att_log(
|
||||||
|
att_prot varchar(15)
|
||||||
|
,who_ami varchar(31) default current_user
|
||||||
|
,att_id bigint default current_connection
|
||||||
|
,trn_id bigint default current_transaction
|
||||||
|
,evt_time time default 'now'
|
||||||
|
,evt_name varchar(20)
|
||||||
|
,swp_interval int
|
||||||
|
);
|
||||||
|
set term ^;
|
||||||
|
create procedure sp_fill_dblevel_log(a_evt_name type of column att_log.evt_name) as
|
||||||
|
declare v_swp_interval int;
|
||||||
|
declare v_protocol type of column att_log.att_prot;
|
||||||
|
begin
|
||||||
|
insert into att_log(
|
||||||
|
att_prot
|
||||||
|
,evt_name
|
||||||
|
) values (
|
||||||
|
rdb$get_context('SYSTEM', 'NETWORK_PROTOCOL')
|
||||||
|
,:a_evt_name
|
||||||
|
);
|
||||||
|
|
||||||
|
end
|
||||||
|
^
|
||||||
|
create or alter trigger trg_detach on disconnect as
|
||||||
|
begin
|
||||||
|
execute procedure sp_fill_dblevel_log('detach');
|
||||||
|
end
|
||||||
|
^
|
||||||
|
create or alter trigger trg_attach on connect as
|
||||||
|
begin
|
||||||
|
execute procedure sp_fill_dblevel_log('attach');
|
||||||
|
end
|
||||||
|
^
|
||||||
|
set term ;^
|
||||||
|
commit;
|
||||||
|
|
||||||
|
recreate table test(s varchar(36) unique);
|
||||||
|
insert into test(s) values('LOCKED_FOR_PAUSE');
|
||||||
|
commit;
|
||||||
|
|
||||||
|
set transaction read committed WAIT;
|
||||||
|
|
||||||
|
update test set s = s where s = 'LOCKED_FOR_PAUSE';
|
||||||
|
|
||||||
|
set term ^;
|
||||||
|
execute block as
|
||||||
|
declare n int = {TX_NUMBER_BEFORE_HANG};
|
||||||
|
declare v_role varchar(31);
|
||||||
|
begin
|
||||||
|
while (n > 0) do
|
||||||
|
in autonomous transaction do
|
||||||
|
insert into test(s) values( rpad('', 36, uuid_to_char(gen_uuid()) ) )
|
||||||
|
returning :n-1 into n;
|
||||||
|
|
||||||
|
v_role = left(replace( uuid_to_char(gen_uuid()), '-', ''), 31);
|
||||||
|
|
||||||
|
begin
|
||||||
|
execute statement ('update /* ES/EDS */ test set s = s where s = ?') ('LOCKED_FOR_PAUSE')
|
||||||
|
on external
|
||||||
|
'localhost:' || rdb$get_context('SYSTEM', 'DB_NAME')
|
||||||
|
as user 'SYSDBA' password 'masterkey' role v_role
|
||||||
|
with autonomous transaction;
|
||||||
|
when any do
|
||||||
|
begin
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
^
|
||||||
|
set term ;^
|
||||||
|
set heading off;
|
||||||
|
select '-- shutdown me now --' from rdb$database;
|
||||||
|
"""
|
||||||
|
|
||||||
|
tmp_sql_file.write_text(test_script)
|
||||||
|
|
||||||
|
#----------------------------------------------------------------
|
||||||
|
|
||||||
|
# Reduce sweep interval to small value (that must be less than SQL_HANG_AFTER_TX_CNT):
|
||||||
|
#
|
||||||
|
act.gfix(switches=['-h', f'{SWP_INTERVAL_TO_CHECK}', act.db.dsn], combine_output = True, io_enc = locale.getpreferredencoding())
|
||||||
|
|
||||||
|
with open(tmp_log_file, 'w') as f:
|
||||||
|
# Launch ISQL which will hang because update conflict.
|
||||||
|
# This ISQl will be 'self-terminated' further because we will change DB state to full shutdown:
|
||||||
|
#
|
||||||
|
p_handed_isql = subprocess.Popen([act.vars['isql'], '-nod', '-i', str(tmp_sql_file),
|
||||||
|
'-user', act.db.user,
|
||||||
|
'-password', act.db.password, act.db.dsn],
|
||||||
|
stdout = f,
|
||||||
|
stderr = subprocess.STDOUT)
|
||||||
|
|
||||||
|
# Let ISQL time to establish connection and fall in hanging state:
|
||||||
|
time.sleep(3)
|
||||||
|
|
||||||
|
try:
|
||||||
|
act.gfix(switches=['-shut', 'full', '-force', '0', act.db.dsn], combine_output = True, io_enc = locale.getpreferredencoding())
|
||||||
|
finally:
|
||||||
|
p_handed_isql.terminate()
|
||||||
|
|
||||||
|
p_handed_isql.wait(MAX_WAIT_FOR_ISQL_TERMINATE)
|
||||||
|
if p_handed_isql.poll() is None:
|
||||||
|
print(f'Hanged ISQL process WAS NOT terminated in {MAX_WAIT_FOR_ISQL_TERMINATE} second(s).!')
|
||||||
|
else:
|
||||||
|
print(f'Hanged ISQL process terminated with retcode = {p_handed_isql.poll()}')
|
||||||
|
|
||||||
|
# Result: log of hanged ISQL must contain now:
|
||||||
|
# Statement failed, SQLSTATE = 08003
|
||||||
|
# connection shutdown
|
||||||
|
# -Database is shutdown.
|
||||||
|
|
||||||
|
act.gfix(switches=['-online', act.db.dsn], combine_output = True, io_enc = locale.getpreferredencoding())
|
||||||
|
assert act.clean_stdout == ''
|
||||||
|
act.reset()
|
||||||
|
|
||||||
|
# Must show: Attributes encrypted, plugin {ENCRYPTION_PLUGIN} - without 'shutdown'!
|
||||||
|
act.gstat(switches=['-h'])
|
||||||
|
print(act.stdout)
|
||||||
|
|
||||||
|
#act.stdout = capsys.readouterr().out
|
||||||
|
#assert act.clean_stdout == act.clean_expected_stdout
|
||||||
|
#act.reset()
|
||||||
|
|
||||||
|
|
||||||
|
#----------------------------------------------------------------
|
||||||
|
|
||||||
|
TEST_QUERY = 'select att_prot,who_ami,evt_name from att_log order by trn_id'
|
||||||
|
final_sql = f"""
|
||||||
|
set count on;
|
||||||
|
set list on;
|
||||||
|
set echo on;
|
||||||
|
{TEST_QUERY};
|
||||||
|
commit;
|
||||||
|
connect '{act.db.dsn}';
|
||||||
|
drop database;
|
||||||
|
quit;
|
||||||
|
"""
|
||||||
|
tmp_sql_file.write_text(final_sql)
|
||||||
|
|
||||||
|
with open(tmp_log_file, 'w') as f:
|
||||||
|
# Explained by Alex, letter 13-dec-2023 13:18.
|
||||||
|
# Following ISQL will create attach that provokes AUTO SWEEP (because Next - OST now greater than SWP_INTERVAL_TO_CHECK).
|
||||||
|
# Problem raised when other attachments were prohibited to use encryption key (and this is default behaviour).
|
||||||
|
# Before fix, SWEEEP was not allowed to use key from this ISQL-attachment.
|
||||||
|
# Following message was added in firebird.log: "Automatic sweep error /Missing database encryption key for your attachment"
|
||||||
|
# But despite problem with establishing connection by SWEEP, its thread already created appropriate lock at that point.
|
||||||
|
# As result, engine remained in wrong state after this: existied attachments could not be closed.
|
||||||
|
# Also, FB process could not be normally stopped.
|
||||||
|
|
||||||
|
MAX_WAIT_AUTO_SWEEP_FINISH = 3
|
||||||
|
p_chk_sql = subprocess.Popen( [ act.vars['isql'],
|
||||||
|
'-nod', '-i', str(tmp_sql_file),
|
||||||
|
'-user', act.db.user,
|
||||||
|
'-password', act.db.password,
|
||||||
|
act.db.dsn
|
||||||
|
],
|
||||||
|
stdout = f,
|
||||||
|
stderr = subprocess.STDOUT,
|
||||||
|
)
|
||||||
|
|
||||||
|
# If the process does not terminate after timeout seconds, raise a TimeoutExpired exception.
|
||||||
|
# It is safe to catch this exception and retry the wait.
|
||||||
|
try:
|
||||||
|
p_chk_sql.wait(timeout = MAX_WAIT_AUTO_SWEEP_FINISH)
|
||||||
|
except subprocess.TimeoutExpired as e:
|
||||||
|
print(f'Could not obtain result for {MAX_WAIT_AUTO_SWEEP_FINISH} seconds:')
|
||||||
|
print(e.__str__())
|
||||||
|
|
||||||
|
p_chk_sql.terminate()
|
||||||
|
p_chk_sql.wait(MAX_WAIT_FOR_ISQL_TERMINATE)
|
||||||
|
|
||||||
|
# Check if child process has terminated. Set and return returncode attribute. Otherwise, returns None.
|
||||||
|
if p_chk_sql.poll() is None:
|
||||||
|
print(f'Final ISQL process WAS NOT terminated in {MAX_WAIT_FOR_ISQL_TERMINATE} second(s).!')
|
||||||
|
else:
|
||||||
|
print(f'Final ISQL process terminated')
|
||||||
|
#print(f'Final ISQL process terminated with retcode = {p_chk_sql.poll()}')
|
||||||
|
|
||||||
|
|
||||||
|
# do NOT put here this:
|
||||||
|
#run_encr_decr(act, 'decrypt', MAX_WAITING_ENCR_FINISH, capsys)
|
||||||
|
# - otherwise pytest will not return control
|
||||||
|
|
||||||
|
with open(tmp_log_file, 'r') as f:
|
||||||
|
for line in f:
|
||||||
|
if line.strip():
|
||||||
|
print('final ISQL log:',line)
|
||||||
|
|
||||||
|
act.expected_stdout = f"""
|
||||||
|
Hanged ISQL process terminated with retcode = 1
|
||||||
|
Attributes encrypted, plugin {ENCRYPTION_PLUGIN}
|
||||||
|
|
||||||
|
Final ISQL process terminated
|
||||||
|
final ISQL log: {TEST_QUERY};
|
||||||
|
final ISQL log: ATT_PROT TCP
|
||||||
|
final ISQL log: WHO_AMI {act.db.user.upper()}
|
||||||
|
final ISQL log: EVT_NAME attach
|
||||||
|
|
||||||
|
final ISQL log: ATT_PROT TCP
|
||||||
|
final ISQL log: WHO_AMI {act.db.user.upper()}
|
||||||
|
final ISQL log: EVT_NAME detach
|
||||||
|
|
||||||
|
final ISQL log: Records affected: 2
|
||||||
|
|
||||||
|
final ISQL log: commit;
|
||||||
|
final ISQL log: drop database;
|
||||||
|
final ISQL log: quit;
|
||||||
|
"""
|
||||||
|
|
||||||
|
act.stdout = capsys.readouterr().out
|
||||||
|
assert act.clean_stdout == act.clean_expected_stdout
|
||||||
|
act.reset()
|
||||||
|
|
||||||
|
# NB! We have to decrypt database now. Otherwise teardown will fail with:
|
||||||
|
# firebird.driver.types.DatabaseError: Missing database encryption key for your attachment
|
||||||
|
# -Plugin fbSampleDbCrypt:
|
||||||
|
# -Crypt key not set
|
||||||
|
#run_encr_decr(act, 'decrypt', MAX_WAITING_ENCR_FINISH, capsys)
|
@ -166,6 +166,7 @@ def run_encr_decr(act: Action, mode, max_wait_encr_thread_finish, capsys):
|
|||||||
|
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.encryption
|
@pytest.mark.encryption
|
||||||
@pytest.mark.version('>=4.0.5')
|
@pytest.mark.version('>=4.0.5')
|
||||||
def test_1(act: Action, tmp_sql_file: Path, tmp_log_file: Path, tmp_gstat_log: Path, capsys):
|
def test_1(act: Action, tmp_sql_file: Path, tmp_log_file: Path, tmp_gstat_log: Path, capsys):
|
||||||
|
@ -70,6 +70,7 @@ STOP_RECURSIVE_ES_AFTER_ITER = 101
|
|||||||
|
|
||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=4.0.5')
|
@pytest.mark.version('>=4.0.5')
|
||||||
def test_1(act: Action, tmp_sql: Path, tmp_log: Path, capsys):
|
def test_1(act: Action, tmp_sql: Path, tmp_log: Path, capsys):
|
||||||
|
|
||||||
|
@ -73,6 +73,7 @@ ADD_DELAY_FOR_RARE = 2
|
|||||||
#
|
#
|
||||||
ITER_LOOP_CNT = 3
|
ITER_LOOP_CNT = 3
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=4.0')
|
@pytest.mark.version('>=4.0')
|
||||||
def test_1(act: Action, tmp_user_freq: User, tmp_user_rare: User, tmp_cleaner_role: Role, capsys):
|
def test_1(act: Action, tmp_user_freq: User, tmp_user_rare: User, tmp_cleaner_role: Role, capsys):
|
||||||
|
|
||||||
@ -244,14 +245,6 @@ def test_1(act: Action, tmp_user_freq: User, tmp_user_rare: User, tmp_cleaner_ro
|
|||||||
commit;
|
commit;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
'''
|
|
||||||
print(sql_init)
|
|
||||||
act.expected_stdout = ''
|
|
||||||
act.stdout = capsys.readouterr().out
|
|
||||||
assert act.clean_stdout == act.clean_expected_stdout
|
|
||||||
act.reset()
|
|
||||||
'''
|
|
||||||
|
|
||||||
act.expected_stdout = ''
|
act.expected_stdout = ''
|
||||||
act.isql(switches = ['-q'], input = sql_init, combine_output = True, io_enc = locale.getpreferredencoding())
|
act.isql(switches = ['-q'], input = sql_init, combine_output = True, io_enc = locale.getpreferredencoding())
|
||||||
assert act.clean_stdout == act.clean_expected_stdout
|
assert act.clean_stdout == act.clean_expected_stdout
|
||||||
|
@ -62,6 +62,7 @@ expected_stdout_isql = """
|
|||||||
-At block line
|
-At block line
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=4.0')
|
@pytest.mark.version('>=4.0')
|
||||||
def test_1(act: Action, tmp_user: User, tmp_role:Role, capsys):
|
def test_1(act: Action, tmp_user: User, tmp_role:Role, capsys):
|
||||||
|
|
||||||
|
@ -139,6 +139,7 @@ expected_stdout = """
|
|||||||
Records affected: 1
|
Records affected: 1
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@pytest.mark.es_eds
|
||||||
@pytest.mark.version('>=4.0')
|
@pytest.mark.version('>=4.0')
|
||||||
def test_1(act: Action, test_user, test_role):
|
def test_1(act: Action, test_user, test_role):
|
||||||
act.expected_stdout = expected_stdout
|
act.expected_stdout = expected_stdout
|
||||||
|
Loading…
Reference in New Issue
Block a user