mirror of
https://github.com/FirebirdSQL/firebird-qa.git
synced 2025-01-22 13:33:07 +01:00
More pytyhon tests
This commit is contained in:
parent
7822a79624
commit
ea95f54d07
@ -40,7 +40,7 @@
|
||||
# qmid: None
|
||||
|
||||
import pytest
|
||||
from threading import Thread
|
||||
from threading import Thread, Barrier
|
||||
from firebird.qa import db_factory, python_act, Action
|
||||
|
||||
# version: 2.5
|
||||
@ -264,7 +264,7 @@ test_script_1 = """
|
||||
set term ;^
|
||||
"""
|
||||
|
||||
def trace_session(act: Action):
|
||||
def trace_session(act: Action, b: Barrier):
|
||||
cfg30 = ['# Trace config, format for 3.0. Generated auto, do not edit!',
|
||||
f'database=%[\\\\/]{act.db.db_path.name}',
|
||||
'{',
|
||||
@ -280,13 +280,16 @@ def trace_session(act: Action):
|
||||
'}']
|
||||
with act.connect_server() as srv:
|
||||
srv.trace.start(config='\n'.join(cfg30))
|
||||
b.wait()
|
||||
for line in srv:
|
||||
print(line)
|
||||
|
||||
@pytest.mark.version('>=3.0')
|
||||
def test_1(act_1: Action, capsys):
|
||||
trace_thread = Thread(target=trace_session, args=[act_1])
|
||||
b = Barrier(2)
|
||||
trace_thread = Thread(target=trace_session, args=[act_1, b])
|
||||
trace_thread.start()
|
||||
b.wait()
|
||||
act_1.isql(switches=['-n'], input=test_script_1)
|
||||
with act_1.connect_server() as srv:
|
||||
for session in list(srv.trace.sessions.keys()):
|
||||
|
@ -16,7 +16,7 @@
|
||||
# qmid: None
|
||||
|
||||
import pytest
|
||||
from threading import Thread
|
||||
from threading import Thread, Barrier
|
||||
from difflib import unified_diff
|
||||
from firebird.qa import db_factory, python_act, Action
|
||||
|
||||
@ -482,7 +482,7 @@ select '*Лев Николаевич Толстой *
|
||||
' from rdb$database;
|
||||
"""
|
||||
|
||||
def trace_session(act: Action):
|
||||
def trace_session(act: Action, b: Barrier):
|
||||
cfg30 = ['# Trace config, format for 3.0. Generated auto, do not edit!',
|
||||
f'database=%[\\\\/]{act.db.db_path.name}',
|
||||
'{',
|
||||
@ -515,17 +515,20 @@ def trace_session(act: Action):
|
||||
with act.connect_server() as srv:
|
||||
srv.encoding = 'utf8'
|
||||
srv.trace.start(config='\n'.join(cfg30))
|
||||
b.wait()
|
||||
for line in srv:
|
||||
pass # we are not interested in trace output
|
||||
|
||||
@pytest.mark.version('>=2.5.1')
|
||||
def test_1(act_1: Action):
|
||||
b = Barrier(2)
|
||||
# Get content of firebird.log BEFORE test
|
||||
with act_1.connect_server() as srv:
|
||||
srv.info.get_log()
|
||||
log_before = srv.readlines()
|
||||
trace_thread = Thread(target=trace_session, args=[act_1])
|
||||
trace_thread = Thread(target=trace_session, args=[act_1, b])
|
||||
trace_thread.start()
|
||||
b.wait()
|
||||
# RUN QUERY WITH NON-ASCII CHARACTERS
|
||||
act_1.isql(switches=['-n', '-q'], input=test_script_1)
|
||||
with act_1.connect_server() as srv:
|
||||
|
@ -20,7 +20,7 @@
|
||||
# qmid: None
|
||||
|
||||
import pytest
|
||||
from threading import Thread
|
||||
from threading import Thread, Barrier
|
||||
from firebird.qa import db_factory, python_act, Action
|
||||
|
||||
# version: 2.5
|
||||
@ -188,7 +188,7 @@ expected_stdout_1 = """
|
||||
SYSDBA:NONE, ISO88591, TCP
|
||||
"""
|
||||
|
||||
def trace_session(act: Action):
|
||||
def trace_session(act: Action, b: Barrier):
|
||||
cfg30 = ['# Trace config, format for 3.0. Generated auto, do not edit!',
|
||||
f'database=%[\\\\/]{act.db.db_path.name}',
|
||||
'{',
|
||||
@ -198,13 +198,16 @@ def trace_session(act: Action):
|
||||
'}']
|
||||
with act.connect_server() as srv:
|
||||
srv.trace.start(config='\n'.join(cfg30))
|
||||
b.wait()
|
||||
for line in srv:
|
||||
print(line.upper())
|
||||
|
||||
@pytest.mark.version('>=3.0')
|
||||
def test_1(act_1: Action, capsys):
|
||||
trace_thread = Thread(target=trace_session, args=[act_1])
|
||||
b = Barrier(2)
|
||||
trace_thread = Thread(target=trace_session, args=[act_1, b])
|
||||
trace_thread.start()
|
||||
b.wait()
|
||||
# make two connections with different charset
|
||||
with act_1.db.connect(charset='utf8'):
|
||||
pass
|
||||
|
@ -9,7 +9,7 @@
|
||||
# qmid: None
|
||||
|
||||
import pytest
|
||||
from firebird.qa import db_factory, isql_act, Action
|
||||
from firebird.qa import db_factory, python_act, Action
|
||||
|
||||
# version: 2.1.5
|
||||
# resources: None
|
||||
@ -48,12 +48,16 @@ db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1)
|
||||
# else:
|
||||
# pass
|
||||
#---
|
||||
#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1)
|
||||
|
||||
|
||||
@pytest.mark.version('>=2.1.5')
|
||||
@pytest.mark.xfail
|
||||
def test_1(db_1):
|
||||
pytest.fail("Test not IMPLEMENTED")
|
||||
|
||||
act_1 = python_act('db_1', substitutions=substitutions_1)
|
||||
|
||||
@pytest.mark.version('>=3.0')
|
||||
def test_1(act_1: Action):
|
||||
with act_1.db.connect() as con:
|
||||
c = con.cursor()
|
||||
# Test non multi-bytes
|
||||
c.execute("with q(s) as (select cast('abcdefghijklmno' as blob sub_type 1 character set utf8) from rdb$database) select overlay (s placing cast('0123456789' as blob sub_type 1 character set utf8) from 5) from q")
|
||||
# Test UTF8
|
||||
c.execute("with q(s) as (select cast('abcdefghijklmno' as blob sub_type 1 character set utf8) from rdb$database) select overlay (s placing cast(_iso8859_1 'áé' as blob sub_type 1 character set utf8) from 5) from q")
|
||||
# Test ISO8859_1
|
||||
c.execute("with q(s) as (select cast('abcdefghijklmno' as blob sub_type 1 character set utf8) from rdb$database) select overlay (s placing cast(_iso8859_1 'áé' as blob sub_type 1 character set iso8859_1) from 5) from q")
|
||||
|
@ -36,6 +36,9 @@
|
||||
# 2.5.9.27152 CS: 1.333s.
|
||||
#
|
||||
#
|
||||
# [pcisar] 17.11.2021
|
||||
# This test is too complicated and fragile (can screw the test environment)
|
||||
# It should be reimplemnted in more robust way, or removed from suite
|
||||
#
|
||||
# tracker_id: CORE-3323
|
||||
# min_versions: ['2.5.1']
|
||||
|
@ -20,30 +20,10 @@
|
||||
#
|
||||
# Samples of call with '-c <path_to_fbclient_dll>':
|
||||
#
|
||||
# fbt_run -b C:\\MIX
|
||||
# irebird
|
||||
# b25in bugs.core_3328 -o localhost/3255 -c C:\\MIX
|
||||
# irebird
|
||||
# b25in
|
||||
# bclient.dll
|
||||
# fbt_run -b C:\\MIX
|
||||
# irebird
|
||||
# b25Csin bugs.core_3328 -o localhost/3249 -c C:\\MIX
|
||||
# irebird
|
||||
# b25csin
|
||||
# bclient.dll
|
||||
# fbt_run -b C:\\MIX
|
||||
# irebird
|
||||
# b40Cs bugs.core_3328 -o localhost/3439 -c C:\\MIX
|
||||
# irebird
|
||||
# b40cs
|
||||
# bclient.dll
|
||||
# fbt_run -b C:\\MIX
|
||||
# irebird
|
||||
# b40sc bugs.core_3328 -o localhost/3430 -c C:\\MIX
|
||||
# irebird
|
||||
# b40sc
|
||||
# bclient.dll & fbt_view -d results.trf
|
||||
# fbt_run -b C:\\MIX\\firebird\\fb25\\bin bugs.core_3328 -o localhost/3255 -c C:\\MIX\\firebird\\fb25\\fbinbclient.dll
|
||||
# fbt_run -b C:\\MIX\\firebird\\fb25Cs\\bin bugs.core_3328 -o localhost/3249 -c C:\\MIX\\firebird\\fb25cs\\bin\\fbclient.dll
|
||||
# fbt_run -b C:\\MIX\\firebird\\fb40Cs bugs.core_3328 -o localhost/3439 -c C:\\MIX\\firebird\\fb40cs\\fbclient.dll
|
||||
# fbt_run -b C:\\MIX\\firebird\\fb40sc bugs.core_3328 -o localhost/3430 -c C:\\MIX\\firebird\\fb40sc\\fbclient.dll & fbt_view -d results.trf
|
||||
#
|
||||
# tracker_id: CORE-3328
|
||||
# min_versions: ['2.5.1']
|
||||
@ -51,17 +31,22 @@
|
||||
# qmid: None
|
||||
|
||||
import pytest
|
||||
from firebird.qa import db_factory, isql_act, Action
|
||||
import time
|
||||
from difflib import unified_diff
|
||||
from threading import Thread
|
||||
from firebird.qa import db_factory, python_act, Action
|
||||
from firebird.driver import ShutdownMethod, ShutdownMode
|
||||
|
||||
# version: 2.5.1
|
||||
# resources: None
|
||||
|
||||
substitutions_1 = [('attachments: [1-9]+', 'attachments: 1'), ('[\\s]+', ' ')]
|
||||
# substitutions_1 = [('attachments: [1-9]+', 'attachments: 1'), ('[\\s]+', ' ')]
|
||||
substitutions_1 = [('database.*shutdown', 'database shutdown')]
|
||||
|
||||
init_script_1 = """
|
||||
create table test(s varchar(36) unique);
|
||||
commit;
|
||||
"""
|
||||
"""
|
||||
|
||||
db_1 = db_factory(sql_dialect=3, init=init_script_1)
|
||||
|
||||
@ -285,16 +270,55 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1)
|
||||
#
|
||||
#
|
||||
#---
|
||||
#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1)
|
||||
|
||||
expected_stdout_1 = """
|
||||
Attributes force write, full shutdown
|
||||
Attributes force write
|
||||
act_1 = python_act('db_1', substitutions=substitutions_1)
|
||||
|
||||
expected_stderr_1 = """
|
||||
Statement failed, SQLSTATE = HY000
|
||||
database /tmp/pytest-of-pcisar/pytest-528/test_10/test.fdb shutdown
|
||||
Statement failed, SQLSTATE = HY000
|
||||
database /tmp/pytest-of-pcisar/pytest-528/test_10/test.fdb shutdown
|
||||
"""
|
||||
|
||||
def run_work(act: Action):
|
||||
test_script = """
|
||||
show version;
|
||||
set term ^;
|
||||
execute block as
|
||||
declare v_role varchar(31);
|
||||
begin
|
||||
v_role = left(replace( uuid_to_char(gen_uuid()), '-', ''), 31);
|
||||
while (1=1) do
|
||||
begin
|
||||
insert into test(s) values( uuid_to_char( gen_uuid() ) );
|
||||
end
|
||||
end
|
||||
^
|
||||
set term ;^
|
||||
"""
|
||||
act.expected_stderr = expected_stderr_1
|
||||
act.isql(switches=['-n'], input=test_script)
|
||||
|
||||
@pytest.mark.version('>=2.5.1')
|
||||
@pytest.mark.xfail
|
||||
def test_1(db_1):
|
||||
pytest.fail("Test not IMPLEMENTED")
|
||||
|
||||
|
||||
@pytest.mark.version('>=3.0')
|
||||
def test_1(act_1: Action):
|
||||
with act_1.connect_server() as srv:
|
||||
srv.info.get_log()
|
||||
log_before = srv.readlines()
|
||||
#
|
||||
work_thread = Thread(target=run_work, args=[act_1])
|
||||
work_thread.start()
|
||||
time.sleep(2)
|
||||
#
|
||||
srv.database.shutdown(database=str(act_1.db.db_path), mode=ShutdownMode.FULL,
|
||||
method=ShutdownMethod.FORCED, timeout=0)
|
||||
srv.database.bring_online(database=str(act_1.db.db_path))
|
||||
#
|
||||
srv.info.get_log()
|
||||
log_after = srv.readlines()
|
||||
#
|
||||
work_thread.join(2)
|
||||
if work_thread.is_alive():
|
||||
pytest.fail('Work thread is still alive')
|
||||
#
|
||||
assert list(unified_diff(log_before, log_after)) == []
|
||||
assert act_1.clean_stderr == act_1.clean_expected_stderr
|
||||
|
@ -18,7 +18,9 @@
|
||||
# qmid: None
|
||||
|
||||
import pytest
|
||||
from firebird.qa import db_factory, isql_act, Action
|
||||
from io import BytesIO
|
||||
from firebird.qa import db_factory, python_act, Action
|
||||
from firebird.driver import SrvRestoreFlag
|
||||
|
||||
# version: 3.0
|
||||
# resources: None
|
||||
@ -29,7 +31,7 @@ init_script_1 = """
|
||||
recreate sequence g1 start with 9223372036854775807 increment by -2147483647;
|
||||
recreate sequence g2 start with -9223372036854775808 increment by 2147483647;
|
||||
commit;
|
||||
"""
|
||||
"""
|
||||
|
||||
db_1 = db_factory(sql_dialect=3, init=init_script_1)
|
||||
|
||||
@ -48,17 +50,25 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1)
|
||||
# if os.path.isfile(fbk):
|
||||
# os.remove(fbk)
|
||||
#---
|
||||
#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1)
|
||||
|
||||
act_1 = python_act('db_1', substitutions=substitutions_1)
|
||||
|
||||
expected_stdout_1 = """
|
||||
Generator G1, current value: 9223372036854775807, initial value: 9223372036854775807, increment: -2147483647
|
||||
Generator G2, current value: -9223372036854775808, initial value: -9223372036854775808, increment: 2147483647
|
||||
"""
|
||||
"""
|
||||
|
||||
@pytest.mark.version('>=3.0')
|
||||
@pytest.mark.xfail
|
||||
def test_1(db_1):
|
||||
pytest.fail("Test not IMPLEMENTED")
|
||||
@pytest.mark.version('>=3.0,<4')
|
||||
def test_1(act_1: Action):
|
||||
with act_1.connect_server() as srv:
|
||||
backup = BytesIO()
|
||||
srv.database.local_backup(database=str(act_1.db.db_path), backup_stream=backup)
|
||||
backup.seek(0)
|
||||
srv.database.local_restore(backup_stream=backup, database=str(act_1.db.db_path),
|
||||
flags=SrvRestoreFlag.REPLACE)
|
||||
act_1.expected_stdout = expected_stdout_1
|
||||
act_1.isql(switches=[], input="show sequ g1; show sequ g2;")
|
||||
assert act_1.clean_stdout == act_1.clean_expected_stdout
|
||||
|
||||
|
||||
# version: 4.0
|
||||
@ -70,7 +80,7 @@ init_script_2 = """
|
||||
recreate sequence g1 start with 9223372036854775807 increment by -2147483647;
|
||||
recreate sequence g2 start with -9223372036854775808 increment by 2147483647;
|
||||
commit;
|
||||
"""
|
||||
"""
|
||||
|
||||
db_2 = db_factory(sql_dialect=3, init=init_script_2)
|
||||
|
||||
@ -89,7 +99,8 @@ db_2 = db_factory(sql_dialect=3, init=init_script_2)
|
||||
# if os.path.isfile(fbk):
|
||||
# os.remove(fbk)
|
||||
#---
|
||||
#act_2 = python_act('db_2', test_script_2, substitutions=substitutions_2)
|
||||
|
||||
act_2 = python_act('db_2', substitutions=substitutions_2)
|
||||
|
||||
expected_stdout_2 = """
|
||||
Generator G1, current value: -9223372034707292162, initial value: 9223372036854775807, increment: -2147483647
|
||||
@ -97,8 +108,15 @@ expected_stdout_2 = """
|
||||
"""
|
||||
|
||||
@pytest.mark.version('>=4.0')
|
||||
@pytest.mark.xfail
|
||||
def test_2(db_2):
|
||||
pytest.fail("Test not IMPLEMENTED")
|
||||
def test_2(act_2: Action):
|
||||
with act_2.connect_server() as srv:
|
||||
backup = BytesIO()
|
||||
srv.database.local_backup(database=str(act_2.db.db_path), backup_stream=backup)
|
||||
backup.seek(0)
|
||||
srv.database.local_restore(backup_stream=backup, database=str(act_2.db.db_path),
|
||||
flags=SrvRestoreFlag.REPLACE)
|
||||
act_2.expected_stdout = expected_stdout_2
|
||||
act_2.isql(switches=[], input="show sequ g1; show sequ g2;")
|
||||
assert act_2.clean_stdout == act_2.clean_expected_stdout
|
||||
|
||||
|
||||
|
@ -20,12 +20,15 @@
|
||||
# qmid: None
|
||||
|
||||
import pytest
|
||||
from firebird.qa import db_factory, isql_act, Action
|
||||
from threading import Thread, Barrier
|
||||
from firebird.qa import db_factory, python_act, Action
|
||||
|
||||
# version: 2.5.1
|
||||
# resources: None
|
||||
|
||||
substitutions_1 = [('^((?!ERROR|ELEMENT).)*$', ''), ('ERROR CREATING TRACE SESSION.*', 'ERROR CREATING TRACE SESSION'), ('.*"FOO" IS NOT A VALID.*', '"FOO" IS NOT A VALID')]
|
||||
substitutions_1 = [('^((?!ERROR|ELEMENT).)*$', ''),
|
||||
('ERROR CREATING TRACE SESSION.*', 'ERROR CREATING TRACE SESSION'),
|
||||
('.*"FOO" IS NOT A VALID.*', '"FOO" IS NOT A VALID')]
|
||||
|
||||
init_script_1 = """"""
|
||||
|
||||
@ -184,17 +187,43 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1)
|
||||
#
|
||||
#
|
||||
#---
|
||||
#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1)
|
||||
|
||||
act_1 = python_act('db_1', substitutions=substitutions_1)
|
||||
|
||||
expected_stdout_1 = """
|
||||
ERROR CREATING TRACE SESSION FOR DATABASE
|
||||
ERROR WHILE PARSING TRACE CONFIGURATION
|
||||
ELEMENT "LOG_STATEMENT_FINISH": "FOO" IS NOT A VALID
|
||||
"""
|
||||
"""
|
||||
|
||||
@pytest.mark.version('>=2.5.1')
|
||||
@pytest.mark.xfail
|
||||
def test_1(db_1):
|
||||
pytest.fail("Test not IMPLEMENTED")
|
||||
def trace_session(act: Action, b: Barrier):
|
||||
cfg30 = ['# Trace config, format for 3.0. Generated auto, do not edit!',
|
||||
f'database=%[\\\\/]{act.db.db_path.name}',
|
||||
'{',
|
||||
' enabled = true',
|
||||
' time_threshold = 0',
|
||||
' log_statement_finish = foo',
|
||||
'}']
|
||||
with act.connect_server() as srv:
|
||||
srv.trace.start(config='\n'.join(cfg30))
|
||||
b.wait()
|
||||
for line in srv:
|
||||
print(line.upper())
|
||||
|
||||
@pytest.mark.version('>=3.0')
|
||||
def test_1(act_1: Action, capsys):
|
||||
b = Barrier(2)
|
||||
trace_thread = Thread(target=trace_session, args=[act_1, b])
|
||||
trace_thread.start()
|
||||
b.wait()
|
||||
act_1.isql(switches=['-n'], input='select 1 as c from rdb$database;')
|
||||
with act_1.connect_server() as srv:
|
||||
for session in list(srv.trace.sessions.keys()):
|
||||
srv.trace.stop(session_id=session)
|
||||
trace_thread.join(1.0)
|
||||
if trace_thread.is_alive():
|
||||
pytest.fail('Trace thread still alive')
|
||||
act_1.expected_stdout = expected_stdout_1
|
||||
act_1.stdout = capsys.readouterr().out
|
||||
assert act_1.clean_stdout == act_1.clean_expected_stdout
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
# title: Inserting Käse into a CHARACTER SET ASCII column succeeds
|
||||
# decription:
|
||||
# 02-mar-2021. Re-implemented in order to have ability to run this test on Linux.
|
||||
# Ttest creates table and fills it with non-ascii characters in init_script, using charset = UTF8.
|
||||
# Test creates table and fills it with non-ascii characters in init_script, using charset = UTF8.
|
||||
# Then it generates .sql script for running it in separae ISQL process.
|
||||
# This script makes connection to test DB using charset = WIN1252 and perform needed DML.
|
||||
# Result will be redirected to .log which will be opened via codecs.open(...encoding='cp1252').
|
||||
@ -20,7 +20,8 @@
|
||||
# qmid:
|
||||
|
||||
import pytest
|
||||
from firebird.qa import db_factory, isql_act, Action
|
||||
from pathlib import Path
|
||||
from firebird.qa import db_factory, python_act, Action, temp_file
|
||||
|
||||
# version: 2.5
|
||||
# resources: None
|
||||
@ -31,7 +32,7 @@ init_script_1 = """
|
||||
create table tascii(s_ascii varchar(10) character set ascii);
|
||||
create table tlatin(s_latin varchar(10) character set latin1);
|
||||
commit;
|
||||
"""
|
||||
"""
|
||||
|
||||
db_1 = db_factory(sql_dialect=3, init=init_script_1)
|
||||
|
||||
@ -114,15 +115,12 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1)
|
||||
#
|
||||
#
|
||||
#---
|
||||
#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1)
|
||||
|
||||
act_1 = python_act('db_1', substitutions=substitutions_1)
|
||||
|
||||
expected_stdout_1 = """
|
||||
insert into tascii values ('Käse');
|
||||
|
||||
Statement failed, SQLSTATE = 22018
|
||||
arithmetic exception, numeric overflow, or string truncation
|
||||
-Cannot transliterate character between character sets
|
||||
|
||||
Records affected: 0
|
||||
|
||||
select s_ascii from tascii;
|
||||
@ -136,9 +134,31 @@ expected_stdout_1 = """
|
||||
Records affected: 1
|
||||
"""
|
||||
|
||||
expected_stderr_1 = """
|
||||
Statement failed, SQLSTATE = 22018
|
||||
arithmetic exception, numeric overflow, or string truncation
|
||||
-Cannot transliterate character between character sets
|
||||
After line 4 in file /tmp/pytest-of-pcisar/pytest-559/test_10/test_script.sql
|
||||
"""
|
||||
|
||||
test_script_1 = temp_file('test_script.sql')
|
||||
|
||||
@pytest.mark.version('>=2.5')
|
||||
@pytest.mark.xfail
|
||||
def test_1(db_1):
|
||||
pytest.fail("Test not IMPLEMENTED")
|
||||
def test_1(act_1: Action, test_script_1: Path):
|
||||
test_script_1.write_text("""
|
||||
set list on;
|
||||
set count on;
|
||||
set echo on;
|
||||
insert into tascii values ('Käse');
|
||||
select s_ascii from tascii;
|
||||
insert into tlatin values ('Käse');
|
||||
select s_latin from tlatin;
|
||||
""", encoding='cp1252')
|
||||
act_1.expected_stdout = expected_stdout_1
|
||||
act_1.expected_stderr = expected_stderr_1
|
||||
act_1.isql(switches=[], input_file=test_script_1, charset='WIN1252')
|
||||
assert act_1.clean_stderr == act_1.clean_expected_stderr
|
||||
assert act_1.clean_stdout == act_1.clean_expected_stdout
|
||||
|
||||
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
# title: Blob transliteration may not happen inside the union
|
||||
# decription:
|
||||
# 02-mar-2021. Re-implemented in order to have ability to run this test on Linux.
|
||||
# Ttest creates table and fills it with non-ascii characters in init_script, using charset = UTF8.
|
||||
# Test creates table and fills it with non-ascii characters in init_script, using charset = UTF8.
|
||||
# Then it generates .sql script for running it in separae ISQL process.
|
||||
# This script makes connection to test DB using charset = WIN1251 and perform needed DML.
|
||||
# Result will be redirected to .log which will be opened via codecs.open(...encoding='cp1251').
|
||||
@ -19,7 +19,8 @@
|
||||
# qmid:
|
||||
|
||||
import pytest
|
||||
from firebird.qa import db_factory, isql_act, Action
|
||||
from pathlib import Path
|
||||
from firebird.qa import db_factory, python_act, Action, temp_file
|
||||
|
||||
# version: 2.5.1
|
||||
# resources: None
|
||||
@ -125,17 +126,33 @@ db_1 = db_factory(charset='WIN1251', sql_dialect=3, init=init_script_1)
|
||||
#
|
||||
#
|
||||
#---
|
||||
#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1)
|
||||
|
||||
act_1 = python_act('db_1', substitutions=substitutions_1)
|
||||
|
||||
expected_stdout_1 = """
|
||||
Это проверка на вывод строки "Йцукёнг"
|
||||
Это проверка на вывод строки "Йцукёнг"
|
||||
Records affected: 2
|
||||
"""
|
||||
"""
|
||||
|
||||
test_script_1 = temp_file('test_script.sql')
|
||||
|
||||
@pytest.mark.version('>=2.5.1')
|
||||
@pytest.mark.xfail
|
||||
def test_1(db_1):
|
||||
pytest.fail("Test not IMPLEMENTED")
|
||||
def test_1(act_1: Action, test_script_1: Path):
|
||||
test_script_1.write_text("""
|
||||
set list on;
|
||||
set blob all;
|
||||
set count on;
|
||||
set list on;
|
||||
|
||||
select msg_blob_id
|
||||
from sp_test
|
||||
union
|
||||
select msg_blob_id
|
||||
from sp_test;
|
||||
""", encoding='cp1251')
|
||||
act_1.expected_stdout = expected_stdout_1
|
||||
act_1.isql(switches=[], input_file=test_script_1, charset='WIN1251')
|
||||
assert act_1.clean_stdout == act_1.clean_expected_stdout
|
||||
|
||||
|
||||
|
@ -41,7 +41,10 @@
|
||||
# qmid: None
|
||||
|
||||
import pytest
|
||||
from firebird.qa import db_factory, isql_act, Action
|
||||
import time
|
||||
from threading import Thread, Barrier
|
||||
from firebird.qa import db_factory, python_act, Action
|
||||
from firebird.driver import DbWriteMode
|
||||
|
||||
# version: 2.5.2
|
||||
# resources: None
|
||||
@ -49,8 +52,8 @@ from firebird.qa import db_factory, isql_act, Action
|
||||
substitutions_1 = []
|
||||
|
||||
init_script_1 = """
|
||||
set bail on;
|
||||
set echo on;
|
||||
set bail on;
|
||||
set echo on;
|
||||
create or alter procedure sp_fill_fix_tab as begin end;
|
||||
create or alter procedure sp_fill_gtt_del_rows as begin end;
|
||||
create or alter procedure sp_fill_gtt_sav_rows as begin end;
|
||||
@ -128,7 +131,7 @@ set echo on;
|
||||
^
|
||||
set term ;^
|
||||
commit;
|
||||
"""
|
||||
"""
|
||||
|
||||
db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1)
|
||||
|
||||
@ -434,7 +437,8 @@ db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1)
|
||||
#
|
||||
#
|
||||
#---
|
||||
#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1)
|
||||
|
||||
act_1 = python_act('db_1', substitutions=substitutions_1)
|
||||
|
||||
expected_stdout_1 = """
|
||||
Check ratio_fetches_to_datapages_for_GTT_DELETE_ROWS: OK
|
||||
@ -445,11 +449,126 @@ expected_stdout_1 = """
|
||||
Check ratio_marks_to_datapages_for_GTT_PRESERVE_ROWS: OK
|
||||
Check ratio_marks_to_row_count_for_GTT_DELETE_ROWS: OK
|
||||
Check ratio_marks_to_row_count_for_GTT_PRESERVE_ROWS: OK
|
||||
"""
|
||||
"""
|
||||
|
||||
def trace_session(act: Action, b: Barrier):
|
||||
cfg30 = ['# Trace config, format for 3.0. Generated auto, do not edit!',
|
||||
f'database=%[\\\\/]{act.db.db_path.name}',
|
||||
'{',
|
||||
' enabled = true',
|
||||
' log_transactions = true',
|
||||
' print_perf = true',
|
||||
#' log_connections = true',
|
||||
#' log_procedure_start = true',
|
||||
#' log_procedure_finish = true',
|
||||
' log_initfini = false',
|
||||
'}']
|
||||
with act.connect_server() as srv:
|
||||
srv.trace.start(config='\n'.join(cfg30))
|
||||
b.wait()
|
||||
for line in srv:
|
||||
print(line)
|
||||
|
||||
@pytest.mark.version('>=2.5.2')
|
||||
@pytest.mark.xfail
|
||||
def test_1(db_1):
|
||||
pytest.fail("Test not IMPLEMENTED")
|
||||
def test_1(act_1: Action, capsys):
|
||||
NUM_ROWS_TO_BE_ADDED = 45000
|
||||
# Change FW to OFF in order to speed up initial data filling
|
||||
with act_1.connect_server() as srv:
|
||||
srv.database.set_write_mode(database=str(act_1.db.db_path), mode=DbWriteMode.ASYNC)
|
||||
# Make initial data filling into PERMANENT table for retrieving later number of data pages
|
||||
# (it should be the same for any kind of tables, including GTTs):
|
||||
with act_1.db.connect() as con:
|
||||
c = con.cursor()
|
||||
c.call_procedure('sp_fill_fix_tab', [NUM_ROWS_TO_BE_ADDED])
|
||||
con.commit()
|
||||
#
|
||||
b = Barrier(2)
|
||||
trace_thread = Thread(target=trace_session, args=[act_1, b])
|
||||
trace_thread.start()
|
||||
b.wait()
|
||||
#
|
||||
with act_1.db.connect() as con1:
|
||||
c = con1.cursor()
|
||||
c.call_procedure('sp_fill_gtt_sav_rows', [NUM_ROWS_TO_BE_ADDED])
|
||||
con1.rollback()
|
||||
|
||||
with act_1.db.connect() as con2:
|
||||
c = con2.cursor()
|
||||
c.call_procedure('sp_fill_gtt_del_rows', [NUM_ROWS_TO_BE_ADDED])
|
||||
con2.rollback()
|
||||
# Somehow sleep is necessary otherwise "sp_fill_gtt_del_rows" will not show up in trace log
|
||||
time.sleep(3)
|
||||
with act_1.connect_server() as srv:
|
||||
for session in list(srv.trace.sessions.keys()):
|
||||
srv.trace.stop(session_id=session)
|
||||
trace_thread.join(3.0)
|
||||
if trace_thread.is_alive():
|
||||
pytest.fail('Trace thread still alive')
|
||||
trace_output = capsys.readouterr().out
|
||||
# Obtain statistics for table T_FIX_TAB in order to estimate numberof data pages
|
||||
dp_cnt = 0
|
||||
act_1.gstat(switches=['-a','-t', 'T_FIX_TAB', '-u', act_1.db.user, '-p', act_1.db.password])
|
||||
for line in act_1.stdout.splitlines():
|
||||
if 'data pages' in line.lower():
|
||||
# Data pages: 1098, data page slots: 1098, average fill: 74% ==> 1098
|
||||
dp_cnt = int(line.replace(',', ' ').split()[2])
|
||||
#
|
||||
gtt_sav_fetches = -1
|
||||
gtt_sav_marks = -1
|
||||
gtt_del_fetches = -1
|
||||
gtt_del_marks = -1
|
||||
gtt_del_trace = ''
|
||||
gtt_sav_trace = ''
|
||||
for line in trace_output.splitlines():
|
||||
if 'fetch' in line:
|
||||
# 2.5.7:
|
||||
# ['370', 'ms,', '1100', 'read(s),', '1358', 'write(s),', '410489', 'fetch(es),', '93294', 'mark(s)']
|
||||
# ['2', 'ms,', '1', 'read(s),', '257', 'write(s),', '1105', 'fetch(es),', '1102', 'mark(s)']
|
||||
# 3.0.2:
|
||||
# 618 ms, 1 read(s), 2210 write(s), 231593 fetch(es), 92334 mark(s)
|
||||
# 14 ms, 1109 write(s), 7 fetch(es), 4 mark(s)
|
||||
words = line.split()
|
||||
for k in range(len(words)):
|
||||
if words[k].startswith('fetch'):
|
||||
if gtt_sav_fetches == -1:
|
||||
gtt_sav_fetches = int(words[k-1])
|
||||
gtt_sav_trace = line.strip()
|
||||
else:
|
||||
gtt_del_fetches = int(words[k-1])
|
||||
gtt_del_trace = line.strip()
|
||||
|
||||
if words[k].startswith('mark'):
|
||||
if gtt_sav_marks==-1:
|
||||
gtt_sav_marks = int(words[k-1])
|
||||
else:
|
||||
gtt_del_marks = int(words[k-1])
|
||||
#
|
||||
check_data = {
|
||||
'ratio_fetches_to_row_count_for_GTT_PRESERVE_ROWS' : (1.00 * gtt_sav_fetches / NUM_ROWS_TO_BE_ADDED, 9.1219, 5.1465),
|
||||
'ratio_fetches_to_row_count_for_GTT_DELETE_ROWS' : (1.00 * gtt_del_fetches / NUM_ROWS_TO_BE_ADDED, 0.0245, 0.00015),
|
||||
'ratio_marks_to_row_count_for_GTT_PRESERVE_ROWS' : (1.00 * gtt_sav_marks / NUM_ROWS_TO_BE_ADDED, 2.0732, 2.05186),
|
||||
'ratio_marks_to_row_count_for_GTT_DELETE_ROWS' : (1.00 * gtt_del_marks / NUM_ROWS_TO_BE_ADDED, 0.0245, 0.000089),
|
||||
'ratio_fetches_to_datapages_for_GTT_PRESERVE_ROWS' : (1.00 * gtt_sav_fetches / dp_cnt, 373.85, 209.776),
|
||||
'ratio_fetches_to_datapages_for_GTT_DELETE_ROWS' : (1.00 * gtt_del_fetches / dp_cnt, 1.0063, 0.00634),
|
||||
'ratio_marks_to_datapages_for_GTT_PRESERVE_ROWS' : (1.00 * gtt_sav_marks / dp_cnt, 84.9672, 83.6358),
|
||||
'ratio_marks_to_datapages_for_GTT_DELETE_ROWS' : (1.00 * gtt_del_marks / dp_cnt, 1.0036, 0.00362),
|
||||
}
|
||||
i = 2 # FB 3+
|
||||
MAX_DIFF_PERCENT = 5.0
|
||||
# THRESHOLD
|
||||
failed_flag = False
|
||||
for k, v in sorted(check_data.items()):
|
||||
msg = ('Check ' + k + ': ' +
|
||||
('OK' if v[i] * ((100 - MAX_DIFF_PERCENT)/100) <= v[0] <= v[i] * (100+MAX_DIFF_PERCENT) / 100
|
||||
else 'value '+str(v[0])+' not in range '+str( v[i] ) + ' +/-' + str(MAX_DIFF_PERCENT) + '%')
|
||||
)
|
||||
print(msg)
|
||||
failed_flag = 'not in range' in msg
|
||||
|
||||
if failed_flag:
|
||||
print('Trace for GTT PRESERVE rows: ' + gtt_sav_trace)
|
||||
print('Trace for GTT DELETE rows: ' + gtt_del_trace)
|
||||
#
|
||||
act_1.expected_stdout = expected_stdout_1
|
||||
act_1.stdout = capsys.readouterr().out
|
||||
assert act_1.clean_stdout == act_1.clean_expected_stdout
|
||||
|
@ -9,7 +9,8 @@
|
||||
# qmid: None
|
||||
|
||||
import pytest
|
||||
from firebird.qa import db_factory, isql_act, Action
|
||||
from firebird.qa import db_factory, python_act, Action
|
||||
from firebird.driver import SrvStatFlag
|
||||
|
||||
# version: 2.5.5
|
||||
# resources: None
|
||||
@ -27,15 +28,23 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1)
|
||||
# runProgram('gstat',['$(DATABASE_LOCATION)bugs.core_3548.fdb','-h','-user',user_name,'-password',user_password])
|
||||
# runProgram('gfix',['$(DATABASE_LOCATION)bugs.core_3548.fdb','-online','-user',user_name,'-password',user_password])
|
||||
#---
|
||||
#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1)
|
||||
|
||||
act_1 = python_act('db_1', substitutions=substitutions_1)
|
||||
|
||||
expected_stdout_1 = """
|
||||
Attributes force write, full shutdown
|
||||
"""
|
||||
"""
|
||||
|
||||
@pytest.mark.version('>=2.5.5')
|
||||
@pytest.mark.xfail
|
||||
def test_1(db_1):
|
||||
pytest.fail("Test not IMPLEMENTED")
|
||||
|
||||
def test_1(act_1: Action):
|
||||
act_1.gfix(switches=['-user', act_1.db.user, '-password', act_1.db.password,
|
||||
'-shut', 'full', '-force', '0', str(act_1.db.db_path)])
|
||||
with act_1.connect_server() as srv:
|
||||
srv.database.get_statistics(database=str(act_1.db.db_path), flags=SrvStatFlag.HDR_PAGES)
|
||||
stats = srv.readlines()
|
||||
act_1.gfix(switches=['-user', act_1.db.user, '-password', act_1.db.password,
|
||||
'-online', str(act_1.db.db_path)])
|
||||
act_1.stdout = '\n'.join(stats)
|
||||
act_1.expected_stdout = expected_stdout_1
|
||||
assert act_1.clean_stdout == act_1.clean_expected_stdout
|
||||
|
||||
|
@ -28,7 +28,9 @@
|
||||
# qmid: None
|
||||
|
||||
import pytest
|
||||
from firebird.qa import db_factory, isql_act, Action
|
||||
import time
|
||||
from threading import Thread, Barrier
|
||||
from firebird.qa import db_factory, python_act, Action
|
||||
|
||||
# version: 3.0
|
||||
# resources: None
|
||||
@ -39,7 +41,7 @@ init_script_1 = """
|
||||
recreate table tfix(id int);
|
||||
recreate global temporary table gtt_ssn(id int) on commit preserve rows;
|
||||
recreate global temporary table gtt_tra(id int) on commit delete rows;
|
||||
"""
|
||||
"""
|
||||
|
||||
db_1 = db_factory(sql_dialect=3, init=init_script_1)
|
||||
|
||||
@ -206,7 +208,7 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1)
|
||||
#
|
||||
# # Output log of trace session, with filtering only interested info:
|
||||
#
|
||||
# # Pwerformance header text (all excessive spaces will be removed before comparison - see below):
|
||||
# # Performance header text (all excessive spaces will be removed before comparison - see below):
|
||||
# perf_header='Table Natural Index Update Insert Delete Backout Purge Expunge'
|
||||
#
|
||||
# checked_events= {
|
||||
@ -239,9 +241,30 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1)
|
||||
#
|
||||
#
|
||||
#---
|
||||
#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1)
|
||||
|
||||
act_1 = python_act('db_1', substitutions=substitutions_1)
|
||||
|
||||
test_script_1 = """
|
||||
set autoddl off;
|
||||
set echo on;
|
||||
set count on;
|
||||
set bail on;
|
||||
insert into tfix(id) values(1);
|
||||
commit;
|
||||
insert into tfix(id) values(2);
|
||||
rollback;
|
||||
insert into gtt_ssn(id) values(1);
|
||||
commit;
|
||||
insert into gtt_ssn(id) values(2);
|
||||
rollback;
|
||||
insert into gtt_tra(id) values(1);
|
||||
commit;
|
||||
insert into gtt_tra(id) values(2);
|
||||
rollback;
|
||||
"""
|
||||
|
||||
expected_stdout_1 = """
|
||||
Statement statistics detected for COMMIT
|
||||
Statement statistics detected for COMMIT
|
||||
Statement statistics detected for ROLLBACK
|
||||
Found performance block header
|
||||
@ -252,11 +275,67 @@ expected_stdout_1 = """
|
||||
Found table statistics for GTT_SSN
|
||||
Statement statistics detected for COMMIT
|
||||
Statement statistics detected for ROLLBACK
|
||||
"""
|
||||
"""
|
||||
|
||||
def trace_session(act: Action, b: Barrier):
|
||||
cfg30 = ['# Trace config, format for 3.0. Generated auto, do not edit!',
|
||||
f'database=%[\\\\/]{act.db.db_path.name}',
|
||||
'{',
|
||||
' enabled = true',
|
||||
' log_transactions = true',
|
||||
' print_perf = true',
|
||||
#' log_connections = true',
|
||||
#' log_procedure_start = true',
|
||||
#' log_procedure_finish = true',
|
||||
' log_initfini = false',
|
||||
'}']
|
||||
with act.connect_server() as srv:
|
||||
srv.trace.start(config='\n'.join(cfg30))
|
||||
b.wait()
|
||||
for line in srv:
|
||||
print(line)
|
||||
|
||||
@pytest.mark.version('>=3.0')
|
||||
@pytest.mark.xfail
|
||||
def test_1(db_1):
|
||||
pytest.fail("Test not IMPLEMENTED")
|
||||
def test_1(act_1: Action, capsys):
|
||||
b = Barrier(2)
|
||||
trace_thread = Thread(target=trace_session, args=[act_1, b])
|
||||
trace_thread.start()
|
||||
b.wait()
|
||||
#
|
||||
act_1.isql(switches=[], input=test_script_1)
|
||||
# do NOT remove this otherwise trace log can contain only message about its start before being closed!
|
||||
time.sleep(3)
|
||||
with act_1.connect_server() as srv:
|
||||
for session in list(srv.trace.sessions.keys()):
|
||||
srv.trace.stop(session_id=session)
|
||||
trace_thread.join(3.0)
|
||||
if trace_thread.is_alive():
|
||||
pytest.fail('Trace thread still alive')
|
||||
trace_output = capsys.readouterr().out
|
||||
# Output log of trace session, with filtering only interested info:
|
||||
# Performance header text (all excessive spaces will be removed before comparison - see below):
|
||||
perf_header='Table Natural Index Update Insert Delete Backout Purge Expunge'
|
||||
|
||||
checked_events= {') COMMIT_TRANSACTION': 'commit',
|
||||
') ROLLBACK_TRANSACTION': 'rollback',
|
||||
') EXECUTE_STATEMENT': 'execute_statement',
|
||||
') START_TRANSACTION': 'start_transaction'
|
||||
}
|
||||
|
||||
i, k = 0, 0
|
||||
watched_event = ''
|
||||
for line in trace_output.splitlines():
|
||||
k += 1
|
||||
e = ''.join([v.upper() for x, v in checked_events.items() if x in line])
|
||||
watched_event = e if e else watched_event
|
||||
|
||||
if ' ms,' in line and ('fetch' in line or 'mark' in line): # One of these *always* must be in trace statistics.
|
||||
print(f'Statement statistics detected for {watched_event}')
|
||||
i += 1
|
||||
if ' '.join(line.split()).upper() == ' '.join(perf_header.split()).upper():
|
||||
print('Found performance block header')
|
||||
if line.startswith('TFIX') or line.startswith('GTT_SSN') or line.startswith('GTT_TRA'):
|
||||
print(f'Found table statistics for {line.split()[0]}')
|
||||
act_1.expected_stdout = expected_stdout_1
|
||||
act_1.stdout = capsys.readouterr().out
|
||||
assert act_1.clean_stdout == act_1.clean_expected_stdout
|
||||
|
@ -34,7 +34,7 @@ init_script_1 = """
|
||||
insert into test_tree values ('5', '4');
|
||||
insert into test_tree values ('6', '2');
|
||||
commit;
|
||||
"""
|
||||
"""
|
||||
|
||||
db_1 = db_factory(sql_dialect=3, init=init_script_1)
|
||||
|
||||
@ -116,12 +116,31 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1)
|
||||
# cleanup( [i.name for i in (f_isql_cmd, f_isql_log)] )
|
||||
#
|
||||
#---
|
||||
#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1)
|
||||
|
||||
test_script_1 = """
|
||||
set planonly;
|
||||
with recursive
|
||||
r_tree as
|
||||
(
|
||||
select tt.id as a, cast(tt.id as varchar(100)) as asum
|
||||
from test_tree tt
|
||||
where tt.id_header is null
|
||||
|
||||
union all
|
||||
|
||||
select tt.id as a, rt.asum || '_' || tt.id
|
||||
from test_tree tt join r_tree rt on rt.a = tt.id_header
|
||||
)
|
||||
select * from r_tree rt2 join test_tree tt2 on tt2.id=rt2.a ;
|
||||
"""
|
||||
|
||||
act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1)
|
||||
|
||||
@pytest.mark.version('>=3.0')
|
||||
@pytest.mark.xfail
|
||||
def test_1(db_1):
|
||||
pytest.fail("Test not IMPLEMENTED")
|
||||
def test_1(act_1: Action):
|
||||
act_1.execute()
|
||||
for line in act_1.stdout.splitlines():
|
||||
if 'PLAN' in line and (line.count('(') - line.count(')') != 0):
|
||||
pytest.fail(f"Difference in opening vs close parenthesis: {line.count('(') - line.count(')')}")
|
||||
|
||||
|
||||
|
@ -35,14 +35,28 @@
|
||||
# qmid: None
|
||||
|
||||
import pytest
|
||||
from firebird.qa import db_factory, isql_act, Action
|
||||
from firebird.qa import db_factory, python_act, Action
|
||||
from firebird.driver import DbInfoCode
|
||||
|
||||
# version: 2.5.2
|
||||
# resources: None
|
||||
|
||||
substitutions_1 = [('[ ]+', ' ')]
|
||||
|
||||
init_script_1 = """"""
|
||||
init_script_1 = """
|
||||
recreate view v_check as
|
||||
select i.mon$page_writes as iostat_pg_writes
|
||||
from mon$attachments a
|
||||
left join mon$io_stats i on a.mon$stat_id = i.mon$stat_id
|
||||
where
|
||||
a.mon$attachment_id <> current_connection
|
||||
and a.mon$remote_protocol is not null
|
||||
and i.mon$stat_group = 1 -- <<< ATTACHMENTS level
|
||||
;
|
||||
|
||||
recreate table test(x int) ;
|
||||
insert into test(x) values(1) ;
|
||||
"""
|
||||
|
||||
db_1 = db_factory(sql_dialect=3, init=init_script_1)
|
||||
|
||||
@ -165,15 +179,57 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1)
|
||||
#
|
||||
#
|
||||
#---
|
||||
#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1)
|
||||
|
||||
expected_stdout_1 = """
|
||||
PAGE_WRITES DIFFERENCE SIGN: 1
|
||||
"""
|
||||
act_1 = python_act('db_1', substitutions=substitutions_1)
|
||||
|
||||
@pytest.mark.version('>=2.5.2')
|
||||
@pytest.mark.xfail
|
||||
def test_1(db_1):
|
||||
pytest.fail("Test not IMPLEMENTED")
|
||||
def test_1(act_1: Action):
|
||||
with act_1.db.connect() as worker_con, act_1.db.connect() as watcher_con:
|
||||
worker = worker_con.cursor()
|
||||
watcher = watcher_con.cursor()
|
||||
sql_mon_query = f'''
|
||||
select count(distinct a.mon$server_pid), min(a.mon$remote_protocol), max(iif(a.mon$remote_protocol is null,1,0))
|
||||
from mon$attachments a
|
||||
where a.mon$attachment_id in ({worker_con.info.id}, {watcher_con.info.id}) or upper(a.mon$user) = upper('cache writer')
|
||||
'''
|
||||
worker.execute(sql_mon_query)
|
||||
server_cnt, server_pro, cache_wrtr = worker.fetchone()
|
||||
if server_pro is None:
|
||||
fba = 'Embedded'
|
||||
elif cache_wrtr == 1:
|
||||
fba = 'SS'
|
||||
elif server_cnt == 2:
|
||||
fba = 'CS'
|
||||
else:
|
||||
f1 = worker_con.info.get_info(DbInfoCode.FETCHES)
|
||||
watcher.execute('select 1 from rdb$database')
|
||||
watcher.fetchall()
|
||||
f1 = worker_con.info.get_info(DbInfoCode.FETCHES)
|
||||
|
||||
fba = 'SC' if f1 ==f2 else 'SS'
|
||||
#
|
||||
if fba == 'SS':
|
||||
# SUPERSERVER SHOULD *NOT* BE PROCESSED BY THIS TEST
|
||||
# COUNTER MON$PAGE_WRITES IS NOT CHANGED DURING RUN,
|
||||
# SO WE CAN ONLY "SIMULATE" PROPER OUTCOME FOR THIS!
|
||||
page_writes_at_point_2, page_writes_at_point_1 = 0, 1
|
||||
else:
|
||||
# Do following in connection-WATCHER:
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
worker_con.execute_immediate('update test set x = 2 rows 1')
|
||||
|
||||
watcher.execute('select * from v_check') # get FIRST value of mon$page_writes
|
||||
page_writes_at_point_1 = watcher.fetchone()[0]
|
||||
|
||||
# Again do in connection-worker: add small change to the data,
|
||||
# otherwise watcher will not get any difference in mon$page_writes:
|
||||
worker_con.execute_immediate('update test set x = 3 rows 1')
|
||||
|
||||
watcher.execute('select * from test')
|
||||
watcher.fetchall()
|
||||
|
||||
watcher_con.commit()
|
||||
watcher.execute('select * from v_check') # get SECOND value of mon$page_writes
|
||||
page_writes_at_point_2 = watcher.fetchone()[0]
|
||||
# PAGE_WRITES DIFFERENCE SIGN: 1
|
||||
assert abs(page_writes_at_point_2 - page_writes_at_point_1) == 1
|
||||
|
@ -19,6 +19,8 @@
|
||||
# 3.0.8.33420 CS: 6.649s.
|
||||
# 2.5.9.27152 SC: 4.410s.
|
||||
#
|
||||
# [pcisar] 17.11.2021
|
||||
# Implementation is complicated, and IMHO not worth of realization
|
||||
# tracker_id: CORE-3658
|
||||
# min_versions: ['2.5.2']
|
||||
# versions: 2.5.2
|
||||
|
@ -19,12 +19,15 @@
|
||||
# qmid: None
|
||||
|
||||
import pytest
|
||||
from firebird.qa import db_factory, isql_act, Action
|
||||
from difflib import unified_diff
|
||||
from firebird.qa import db_factory, python_act, Action
|
||||
|
||||
# version: 2.5.2
|
||||
# resources: None
|
||||
|
||||
substitutions_1 = [('STATEMENT FAILED, SQLSTATE = HY000', ''), ('RECORD NOT FOUND FOR USER: TMP\\$C3732', ''), ('AFTER LINE.*', '')]
|
||||
substitutions_1 = [('STATEMENT FAILED, SQLSTATE = HY000', ''),
|
||||
('RECORD NOT FOUND FOR USER: TMP\\$C3732', ''),
|
||||
('AFTER LINE.*', '')]
|
||||
|
||||
init_script_1 = """"""
|
||||
|
||||
@ -158,12 +161,27 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1)
|
||||
#
|
||||
#
|
||||
#---
|
||||
#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1)
|
||||
|
||||
act_1 = python_act('db_1', substitutions=substitutions_1)
|
||||
|
||||
test_script_1 = """
|
||||
create role REPL_ADMIN;
|
||||
create user tmp$c3732 password '12345';
|
||||
grant repl_admin to tmp$c3732;
|
||||
revoke all on all from tmp$c3732;
|
||||
drop user tmp$c3732;
|
||||
drop role REPL_ADMIN;
|
||||
exit;
|
||||
"""
|
||||
|
||||
@pytest.mark.version('>=2.5.2')
|
||||
@pytest.mark.xfail
|
||||
def test_1(db_1):
|
||||
pytest.fail("Test not IMPLEMENTED")
|
||||
|
||||
def test_1(act_1: Action):
|
||||
with act_1.connect_server() as srv:
|
||||
srv.info.get_log()
|
||||
log_before = srv.readlines()
|
||||
act_1.isql(switches=['-q'], input=test_script_1)
|
||||
with act_1.connect_server() as srv:
|
||||
srv.info.get_log()
|
||||
log_after = srv.readlines()
|
||||
assert list(unified_diff(log_before, log_after)) == []
|
||||
|
||||
|
@ -12,7 +12,9 @@
|
||||
# qmid: None
|
||||
|
||||
import pytest
|
||||
from firebird.qa import db_factory, isql_act, Action
|
||||
import socket
|
||||
import getpass
|
||||
from firebird.qa import db_factory, python_act, Action
|
||||
|
||||
# version: 3.0
|
||||
# resources: None
|
||||
@ -46,16 +48,16 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1)
|
||||
# cur.close()
|
||||
#
|
||||
#---
|
||||
#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1)
|
||||
|
||||
expected_stdout_1 = """
|
||||
Check of remote_host: passed
|
||||
Check of remote_os_user: passed
|
||||
"""
|
||||
act_1 = python_act('db_1', substitutions=substitutions_1)
|
||||
|
||||
@pytest.mark.version('>=3.0')
|
||||
@pytest.mark.xfail
|
||||
def test_1(db_1):
|
||||
pytest.fail("Test not IMPLEMENTED")
|
||||
|
||||
|
||||
def test_1(act_1: Action):
|
||||
with act_1.db.connect() as con:
|
||||
c = con.cursor()
|
||||
c.execute('select mon$remote_host, mon$remote_os_user from mon$attachments where mon$attachment_id=current_connection')
|
||||
r = c.fetchone()
|
||||
if r[0].upper() != socket.gethostname().upper():
|
||||
pytest.fail(f'FAILED check remote_host: got "{r[0]}" instead of "{socket.gethostname()}"')
|
||||
if r[1].upper() != getpass.getuser().upper():
|
||||
pytest.fail(f'FAILED check remote_os_user: got "{r[1]}" instead of "{getpass.getuser()}"')
|
||||
|
@ -38,7 +38,7 @@ substitutions_1 = []
|
||||
|
||||
init_script_1 = """"""
|
||||
|
||||
db_1 = db_factory(sql_dialect=3, init=init_script_1)
|
||||
#db_1 = db_factory(sql_dialect=3, init=init_script_1)
|
||||
|
||||
# test_script_1
|
||||
#---
|
||||
@ -47,10 +47,9 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1)
|
||||
#---
|
||||
#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1)
|
||||
|
||||
|
||||
@pytest.mark.version('>=3.0')
|
||||
@pytest.mark.xfail
|
||||
def test_1(db_1):
|
||||
pytest.fail("Test not IMPLEMENTED")
|
||||
def test_1():
|
||||
# This test should PASS, as there is nothing to check because of changed trace config format
|
||||
pass
|
||||
|
||||
|
||||
|
@ -11,7 +11,9 @@
|
||||
# qmid: None
|
||||
|
||||
import pytest
|
||||
from firebird.qa import db_factory, isql_act, Action
|
||||
from threading import Thread, Barrier
|
||||
from firebird.qa import db_factory, python_act, Action
|
||||
from firebird.driver import DatabaseError
|
||||
|
||||
# version: 2.5
|
||||
# resources: None
|
||||
@ -188,17 +190,42 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1)
|
||||
#
|
||||
#
|
||||
#---
|
||||
#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1)
|
||||
|
||||
expected_stdout_1 = """
|
||||
error text: Error while preparing SQL statement:
|
||||
error text: - SQLCODE: -104
|
||||
error text: - Unexpected end of command - line 1, column 1
|
||||
"""
|
||||
act_1 = python_act('db_1', substitutions=substitutions_1)
|
||||
|
||||
def trace_session(act: Action, b: Barrier):
|
||||
cfg30 = ['# Trace config, format for 3.0. Generated auto, do not edit!',
|
||||
f'database=%[\\\\/]{act.db.db_path.name}',
|
||||
'{',
|
||||
' enabled = true',
|
||||
' time_threshold = 0',
|
||||
' log_statement_finish = true',
|
||||
'}']
|
||||
with act.connect_server() as srv:
|
||||
srv.trace.start(config='\n'.join(cfg30))
|
||||
b.wait()
|
||||
for line in srv:
|
||||
pass # We are not interested in trace output
|
||||
|
||||
@pytest.mark.version('>=2.5')
|
||||
@pytest.mark.xfail
|
||||
def test_1(db_1):
|
||||
pytest.fail("Test not IMPLEMENTED")
|
||||
|
||||
def test_1(act_1: Action, capsys):
|
||||
b = Barrier(2)
|
||||
trace_thread = Thread(target=trace_session, args=[act_1, b])
|
||||
trace_thread.start()
|
||||
b.wait()
|
||||
# empty query
|
||||
with act_1.db.connect() as con:
|
||||
c = con.cursor()
|
||||
try:
|
||||
c.execute('') # This may crash the server
|
||||
except Exception as exc:
|
||||
pass
|
||||
#
|
||||
with act_1.connect_server() as srv:
|
||||
for session in list(srv.trace.sessions.keys()):
|
||||
srv.trace.stop(session_id=session)
|
||||
trace_thread.join(1.0)
|
||||
if trace_thread.is_alive():
|
||||
pytest.fail('Trace thread still alive')
|
||||
# If we got here, the server lives so test passed
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
# qmid: None
|
||||
|
||||
import pytest
|
||||
from firebird.qa import db_factory, isql_act, Action
|
||||
from firebird.qa import db_factory, python_act, Action
|
||||
|
||||
# version: 2.5.3
|
||||
# resources: None
|
||||
@ -61,7 +61,7 @@ init_script_1 = """
|
||||
commit
|
||||
^
|
||||
set term ;^
|
||||
"""
|
||||
"""
|
||||
|
||||
db_1 = db_factory(sql_dialect=3, init=init_script_1)
|
||||
|
||||
@ -103,12 +103,23 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1)
|
||||
#
|
||||
#
|
||||
#---
|
||||
#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1)
|
||||
|
||||
act_1 = python_act('db_1', substitutions=substitutions_1)
|
||||
|
||||
@pytest.mark.version('>=2.5.3')
|
||||
@pytest.mark.xfail
|
||||
def test_1(db_1):
|
||||
pytest.fail("Test not IMPLEMENTED")
|
||||
|
||||
|
||||
def test_1(act_1: Action):
|
||||
run_cnt = 20
|
||||
with act_1.db.connect() as con:
|
||||
c = con.cursor()
|
||||
mem_usage = []
|
||||
for i in range(0, run_cnt):
|
||||
c.execute('select id from sp_main')
|
||||
c.fetchall()
|
||||
mem_usage.append(con.info.current_memory)
|
||||
max_mem_leak = 16384 # FB 3+
|
||||
print(mem_usage)
|
||||
for i in range(2, run_cnt):
|
||||
m0 = mem_usage[i-1]
|
||||
m1 = mem_usage[i]
|
||||
if m1 - m0 >= max_mem_leak:
|
||||
pytest.fail(f'Unexpected memory leak: {m1-m0} bytes, exceeds threshold = {max_mem_leak}')
|
||||
|
Loading…
Reference in New Issue
Block a user