6
0
mirror of https://github.com/FirebirdSQL/firebird-qa.git synced 2025-01-22 21:43:06 +01:00

More pyton tests

This commit is contained in:
Pavel Císař 2021-11-12 18:29:54 +01:00
parent c893f5c946
commit e7b07eade0
13 changed files with 1280 additions and 696 deletions

View File

@ -34,12 +34,19 @@
# qmid: None # qmid: None
import pytest import pytest
from firebird.qa import db_factory, isql_act, Action import time
import subprocess
from pathlib import Path
from firebird.qa import db_factory, python_act, Action, temp_file
# version: 2.5.6 # version: 2.5.6
# resources: None # resources: None
substitutions_1 = [('0: CREATE INDEX LOG: RDB_EXPR_BLOB.*', '0: CREATE INDEX LOG: RDB_EXPR_BLOB'), ('BULK_INSERT_START.*', 'BULK_INSERT_START'), ('BULK_INSERT_FINISH.*', 'BULK_INSERT_FINISH'), ('CREATE_INDX_START.*', 'CREATE_INDX_START'), ('AFTER LINE.*', 'AFTER LINE')] substitutions_1 = [('0: CREATE INDEX LOG: RDB_EXPR_BLOB.*', '0: CREATE INDEX LOG: RDB_EXPR_BLOB'),
('BULK_INSERT_START.*', 'BULK_INSERT_START'),
('BULK_INSERT_FINISH.*', 'BULK_INSERT_FINISH'),
('CREATE_INDX_START.*', 'CREATE_INDX_START'),
('AFTER LINE.*', 'AFTER LINE')]
init_script_1 = """ init_script_1 = """
create or alter procedure sp_ins(n int) as begin end; create or alter procedure sp_ins(n int) as begin end;
@ -266,7 +273,11 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1)
# #
# cleanup( [i.name for i in (f_bulk_insert_sql, f_create_indx_sql, f_bulk_insert_log, f_create_indx_log)] ) # cleanup( [i.name for i in (f_bulk_insert_sql, f_create_indx_sql, f_bulk_insert_log, f_create_indx_log)] )
#--- #---
#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1)
act_1 = python_act('db_1', substitutions=substitutions_1)
tmp_file_bi_in = temp_file('bulk_insert.sql')
tmp_file_bi_out = temp_file('bulk_insert.out')
expected_stdout_1 = """ expected_stdout_1 = """
0: BULK INSERTS LOG: BULK_INSERT_START 0: BULK INSERTS LOG: BULK_INSERT_START
@ -274,7 +285,7 @@ expected_stdout_1 = """
0: CREATE INDEX LOG: INSERTS_STATE OK, IS RUNNING 0: CREATE INDEX LOG: INSERTS_STATE OK, IS RUNNING
0: CREATE INDEX LOG: CREATE_INDX_START 0: CREATE INDEX LOG: CREATE_INDX_START
0: CREATE INDEX LOG: SET TRANSACTION WAIT; 0: CREATE INDEX LOG: SET TRANSACTION WAIT;
0: CREATE INDEX LOG: CREATE INDEX TEST_WAIT ON TEST COMPUTED BY( 'WAIT'|| S ); 0: CREATE INDEX LOG: CREATE INDEX TEST_WAIT ON TEST COMPUTED BY('WAIT'|| S);
0: CREATE INDEX LOG: COMMIT; 0: CREATE INDEX LOG: COMMIT;
0: CREATE INDEX LOG: SET ECHO OFF; 0: CREATE INDEX LOG: SET ECHO OFF;
0: CREATE INDEX LOG: INSERTS_STATE OK, FINISHED 0: CREATE INDEX LOG: INSERTS_STATE OK, FINISHED
@ -282,7 +293,7 @@ expected_stdout_1 = """
0: CREATE INDEX LOG: RDB$UNIQUE_FLAG 0 0: CREATE INDEX LOG: RDB$UNIQUE_FLAG 0
0: CREATE INDEX LOG: RDB$INDEX_INACTIVE 0 0: CREATE INDEX LOG: RDB$INDEX_INACTIVE 0
0: CREATE INDEX LOG: RDB_EXPR_BLOB 0: CREATE INDEX LOG: RDB_EXPR_BLOB
0: CREATE INDEX LOG: ( 'WAIT'|| S ) 0: CREATE INDEX LOG: ('WAIT'|| S)
0: CREATE INDEX LOG: RECORDS AFFECTED: 1 0: CREATE INDEX LOG: RECORDS AFFECTED: 1
0: CREATE INDEX LOG: SET PLAN ON; 0: CREATE INDEX LOG: SET PLAN ON;
0: CREATE INDEX LOG: SELECT 1 FROM TEST WHERE 'WAIT'|| S > '' ROWS 0; 0: CREATE INDEX LOG: SELECT 1 FROM TEST WHERE 'WAIT'|| S > '' ROWS 0;
@ -295,31 +306,166 @@ expected_stdout_1 = """
1: CREATE INDEX LOG: INSERTS_STATE OK, IS RUNNING 1: CREATE INDEX LOG: INSERTS_STATE OK, IS RUNNING
1: CREATE INDEX LOG: CREATE_INDX_START 1: CREATE INDEX LOG: CREATE_INDX_START
1: CREATE INDEX LOG: SET TRANSACTION NO WAIT; 1: CREATE INDEX LOG: SET TRANSACTION NO WAIT;
1: CREATE INDEX LOG: CREATE INDEX TEST_NO_WAIT ON TEST COMPUTED BY( 'NO_WAIT'|| S ); 1: CREATE INDEX LOG: CREATE INDEX TEST_NO_WAIT ON TEST COMPUTED BY('NO_WAIT'|| S);
1: CREATE INDEX LOG: COMMIT; 1: CREATE INDEX LOG: COMMIT;
1: CREATE INDEX LOG: STATEMENT FAILED, SQLSTATE = 40001 1: CREATE INDEX LOG: STATEMENT FAILED, SQLSTATE = 40001
1: CREATE INDEX LOG: LOCK CONFLICT ON NO WAIT TRANSACTION 1: CREATE INDEX LOG: LOCK CONFLICT ON NO WAIT TRANSACTION
1: CREATE INDEX LOG: -UNSUCCESSFUL METADATA UPDATE 1: CREATE INDEX LOG: -UNSUCCESSFUL METADATA UPDATE
1: CREATE INDEX LOG: -OBJECT TABLE "TEST" IS IN USE 1: CREATE INDEX LOG: -OBJECT TABLE "TEST" IS IN USE
1: CREATE INDEX LOG: AFTER LINE
2: BULK INSERTS LOG: BULK_INSERT_START 2: BULK INSERTS LOG: BULK_INSERT_START
2: BULK INSERTS LOG: BULK_INSERT_FINISH 2: BULK INSERTS LOG: BULK_INSERT_FINISH
2: CREATE INDEX LOG: INSERTS_STATE OK, IS RUNNING 2: CREATE INDEX LOG: INSERTS_STATE OK, IS RUNNING
2: CREATE INDEX LOG: CREATE_INDX_START 2: CREATE INDEX LOG: CREATE_INDX_START
2: CREATE INDEX LOG: SET TRANSACTION LOCK TIMEOUT 1; 2: CREATE INDEX LOG: SET TRANSACTION LOCK TIMEOUT 1;
2: CREATE INDEX LOG: CREATE INDEX TEST_LOCK_TIMEOUT_1 ON TEST COMPUTED BY( 'LOCK_TIMEOUT_1'|| S ); 2: CREATE INDEX LOG: CREATE INDEX TEST_LOCK_TIMEOUT_1 ON TEST COMPUTED BY('LOCK_TIMEOUT_1'|| S);
2: CREATE INDEX LOG: COMMIT; 2: CREATE INDEX LOG: COMMIT;
2: CREATE INDEX LOG: STATEMENT FAILED, SQLSTATE = 40001 2: CREATE INDEX LOG: STATEMENT FAILED, SQLSTATE = 40001
2: CREATE INDEX LOG: LOCK TIME-OUT ON WAIT TRANSACTION 2: CREATE INDEX LOG: LOCK TIME-OUT ON WAIT TRANSACTION
2: CREATE INDEX LOG: -UNSUCCESSFUL METADATA UPDATE 2: CREATE INDEX LOG: -UNSUCCESSFUL METADATA UPDATE
2: CREATE INDEX LOG: -OBJECT TABLE "TEST" IS IN USE 2: CREATE INDEX LOG: -OBJECT TABLE "TEST" IS IN USE
2: CREATE INDEX LOG: AFTER LINE """
"""
@pytest.mark.version('>=2.5.6') @pytest.mark.version('>=2.5.6')
@pytest.mark.xfail def test_1(act_1: Action, tmp_file_bi_in: Path, tmp_file_bi_out: Path, capsys):
def test_1(db_1): # NB-1: value of 'rows_to_add' must have value that will require at least
pytest.fail("Test not IMPLEMENTED") # 4...5 seconds for inserting such number of rows
# NB-2: FB 2.5 makes DML *faster* than 3.0 in single-connection mode!
rows_to_add = 1000
tmp_file_bi_in.write_text (f'''
set bail on;
set list on;
-- do NOT use it !! >>> alter sequence g restart with 0; -- gen_id(g,1) will return 0 rather than 1 since 06-aug-2020 on FB 4.x !!
delete from test;
set term ^;
execute block as
declare c bigint;
begin
c = gen_id(g, -gen_id(g, 0)); -- restart sequence
end
^
set term ;^
commit;
set transaction lock timeout 7; -- THIS LOCK TIMEOUT SERVES ONLY FOR DELAY, see below auton Tx start.
select current_timestamp as bulk_insert_start from rdb$database;
set term ^;
execute block as
declare i int;
begin
execute procedure sp_ins({rows_to_add});
begin
-- #########################################################
-- ####################### D E L A Y #####################
-- #########################################################
in autonomous transaction do
insert into test( x ) values({rows_to_add}); -- this will cause delay because of duplicate in index
when any do
begin
i = gen_id(g,1);
end
end
end
^
set term ;^
commit;
select current_timestamp as bulk_insert_finish from rdb$database;
''')
tx_param = ['WAIT', 'NO WAIT', 'LOCK TIMEOUT 1']
#
i = 0
#
for tx_decl in tx_param:
idx_name = tx_decl.replace(' ', '_')
idx_expr = "'" + idx_name + "'|| s"
sql_create_indx = f'''
set bail on;
set list on;
set blob all;
select
iif( gen_id(g,0) > 0 and gen_id(g,0) < 1 + {rows_to_add},
'OK, IS RUNNING',
iif( gen_id(g,0) <=0,
'WRONG: not yet started, current gen_id='||gen_id(g,0),
'WRONG: already finished, rows_to_add='|| {rows_to_add} ||', current gen_id='||gen_id(g,0)
)
) as inserts_state,
current_timestamp as create_indx_start
from rdb$database;
set autoddl off;
commit;
set echo on;
set transaction {tx_decl};
create index test_{idx_name} on test computed by({idx_expr});
commit;
set echo off;
select
iif( gen_id(g,0) >= 1 + {rows_to_add},
'OK, FINISHED',
'SOMETHING WRONG: current gen_id=' || gen_id(g,0)||', rows_to_add='|| {rows_to_add}
) as inserts_state
from rdb$database;
set count on;
select
rdb$index_name
,coalesce(rdb$unique_flag,0) as rdb$unique_flag
,coalesce(rdb$index_inactive,0) as rdb$index_inactive
,rdb$expression_source as rdb_expr_blob
from rdb$indices ri
where ri.rdb$index_name = upper( 'test_{idx_name}' )
;
set count off;
set echo on;
set plan on;
select 1 from test where {idx_expr} > '' rows 0;
set plan off;
set echo off;
commit;
drop index test_{idx_name};
commit;
'''
with open(tmp_file_bi_out, mode='w') as f_bulk_insert_log:
# This will insert rows and then stay in pause 10 seconds:
p_bulk_insert = subprocess.Popen([act_1.vars['isql'], act_1.db.dsn,
'-user', act_1.db.user,
'-password', act_1.db.password,
'-q', '-i', str(tmp_file_bi_in)],
stdout = f_bulk_insert_log,
stderr = subprocess.STDOUT
)
#act_1.isql(switches=['-q'], input=sql_bulk_insert)
#bulk_insert_log = act_1.stdout
# 3.0 Classic: seems that it requires at least 2 seconds for ISQL be loaded into memory.
time.sleep(3)
# This will wait until first ISQL finished
act_1.expected_stderr = 'DISABLED'
act_1.isql(switches=['-q', '-n'], input=sql_create_indx)
time.sleep(7) # NB: this delay plus previous (3+5=8) must be GREATER than lock timeout in <sql_bulk_insert>
p_bulk_insert.terminate()
bulk_insert_log = tmp_file_bi_out.read_text()
create_indx_log = act_1.stdout + act_1.stderr
for line in bulk_insert_log.splitlines():
if line.split():
print( str(i)+': BULK INSERTS LOG: '+line.strip().upper() )
for line in create_indx_log.splitlines():
if line.split():
print( str(i)+': CREATE INDEX LOG: '+line.strip().upper() )
#
i += 1
# Checks
act_1.reset()
act_1.stdout = capsys.readouterr().out
act_1.expected_stdout = expected_stdout_1
assert act_1.clean_stdout == act_1.clean_expected_stdout

View File

@ -32,7 +32,61 @@ 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 test_script_1 = """
set list on;
-- binary literal ::= { x | X } <quote> [ { <hexit> <hexit> }... ] <quote>
select x'1' from rdb$database; -- raises: token unknown because length is odd
select x'11' from rdb$database; -- must raise: token unknown because length is odd
select x'0123456789' from rdb$database;
select x'01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789' from rdb$database;
-- must raise: token unknown because last char is not hexit
select x'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678x' from rdb$database;
select uuid_to_char(x'BA1749B583BF9146B360F54E25FE583E') from rdb$database;
-- ##############################################################################
-- Numeric literal: { 0x | 0X } <hexit> [ <hexit>... ]
-- https://firebirdsql.org/refdocs/langrefupd25-bigint.html
recreate view v_test as
select
+-0x1 "-1(a)"
,-+-0xf "+15"
,0x7FFF "32767"
,0x8000 "32768"
,0xFFFF "65535"
,0x10000 "65536(a)"
,0x000000000010000 "65536(b)"
,0x80000000 "-2147483648"
,0x080000000 "+2147483648(a)"
,0x000000080000000 "+2147483648(b)"
,0XFFFFFFFF "-1(b)"
,0X0FFFFFFFF "+4294967295"
,0x100000000 "+4294967296(a)"
,0x0000000100000000 "+4294967296(b)"
,0X7FFFFFFFFFFFFFFF "9223372036854775807"
,0x8000000000000000 "-9223372036854775808"
,0x8000000000000001 "-9223372036854775807"
,0x8000000000000002 "-9223372036854775806"
,0xffffffffffffffff "-1(c)"
from rdb$database;
select * from v_test;
-- If the number of <hexit> is greater than 8, the constant data type is a signed BIGINT
-- If it's less or equal than 8, the data type is a signed INTEGER
set sqlda_display on;
select * from v_test rows 0;
set sqlda_display off;
"""
#--- #---
# #
# import os # import os
@ -88,108 +142,114 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1)
# cleanup( (f_sql_log.name, f_sql_err.name) ) # cleanup( (f_sql_log.name, f_sql_err.name) )
# #
#--- #---
#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1)
act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1)
expected_stdout_1 = """ expected_stdout_1 = """
STDOUT: CONSTANT 11 CONSTANT 11
STDOUT: CONSTANT 0123456789 CONSTANT 0123456789
STDOUT: CONSTANT 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 CONSTANT 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
STDOUT: UUID_TO_CHAR BA1749B5-83BF-9146-B360-F54E25FE583E UUID_TO_CHAR BA1749B5-83BF-9146-B360-F54E25FE583E
STDOUT: -1(a) -1 -1(a) -1
STDOUT: +15 15 +15 15
STDOUT: 32767 32767 32767 32767
STDOUT: 32768 32768 32768 32768
STDOUT: 65535 65535 65535 65535
STDOUT: 65536(a) 65536 65536(a) 65536
STDOUT: 65536(b) 65536 65536(b) 65536
STDOUT: -2147483648 -2147483648 -2147483648 -2147483648
STDOUT: +2147483648(a) 2147483648 +2147483648(a) 2147483648
STDOUT: +2147483648(b) 2147483648 +2147483648(b) 2147483648
STDOUT: -1(b) -1 -1(b) -1
STDOUT: +4294967295 4294967295 +4294967295 4294967295
STDOUT: +4294967296(a) 4294967296 +4294967296(a) 4294967296
STDOUT: +4294967296(b) 4294967296 +4294967296(b) 4294967296
STDOUT: 9223372036854775807 9223372036854775807 9223372036854775807 9223372036854775807
STDOUT: -9223372036854775808 -9223372036854775808 -9223372036854775808 -9223372036854775808
STDOUT: -9223372036854775807 -9223372036854775807 -9223372036854775807 -9223372036854775807
STDOUT: -9223372036854775806 -9223372036854775806 -9223372036854775806 -9223372036854775806
STDOUT: -1(c) -1 -1(c) -1
STDOUT: INPUT message field count: 0 INPUT message field count: 0
STDOUT: OUTPUT message field count: 19 OUTPUT message field count: 19
STDOUT: 01: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 01: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4
STDOUT: : name: -1(a) alias: -1(a) : name: -1(a) alias: -1(a)
STDOUT: : table: V_TEST owner: SYSDBA : table: V_TEST owner: SYSDBA
STDOUT: 02: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 02: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4
STDOUT: : name: +15 alias: +15 : name: +15 alias: +15
STDOUT: : table: V_TEST owner: SYSDBA : table: V_TEST owner: SYSDBA
STDOUT: 03: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 03: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4
STDOUT: : name: 32767 alias: 32767 : name: 32767 alias: 32767
STDOUT: : table: V_TEST owner: SYSDBA : table: V_TEST owner: SYSDBA
STDOUT: 04: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 04: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4
STDOUT: : name: 32768 alias: 32768 : name: 32768 alias: 32768
STDOUT: : table: V_TEST owner: SYSDBA : table: V_TEST owner: SYSDBA
STDOUT: 05: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 05: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4
STDOUT: : name: 65535 alias: 65535 : name: 65535 alias: 65535
STDOUT: : table: V_TEST owner: SYSDBA : table: V_TEST owner: SYSDBA
STDOUT: 06: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 06: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4
STDOUT: : name: 65536(a) alias: 65536(a) : name: 65536(a) alias: 65536(a)
STDOUT: : table: V_TEST owner: SYSDBA : table: V_TEST owner: SYSDBA
STDOUT: 07: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 07: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8
STDOUT: : name: 65536(b) alias: 65536(b) : name: 65536(b) alias: 65536(b)
STDOUT: : table: V_TEST owner: SYSDBA : table: V_TEST owner: SYSDBA
STDOUT: 08: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 08: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4
STDOUT: : name: -2147483648 alias: -2147483648 : name: -2147483648 alias: -2147483648
STDOUT: : table: V_TEST owner: SYSDBA : table: V_TEST owner: SYSDBA
STDOUT: 09: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 09: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8
STDOUT: : name: +2147483648(a) alias: +2147483648(a) : name: +2147483648(a) alias: +2147483648(a)
STDOUT: : table: V_TEST owner: SYSDBA : table: V_TEST owner: SYSDBA
STDOUT: 10: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 10: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8
STDOUT: : name: +2147483648(b) alias: +2147483648(b) : name: +2147483648(b) alias: +2147483648(b)
STDOUT: : table: V_TEST owner: SYSDBA : table: V_TEST owner: SYSDBA
STDOUT: 11: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4 11: sqltype: 496 LONG Nullable scale: 0 subtype: 0 len: 4
STDOUT: : name: -1(b) alias: -1(b) : name: -1(b) alias: -1(b)
STDOUT: : table: V_TEST owner: SYSDBA : table: V_TEST owner: SYSDBA
STDOUT: 12: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 12: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8
STDOUT: : name: +4294967295 alias: +4294967295 : name: +4294967295 alias: +4294967295
STDOUT: : table: V_TEST owner: SYSDBA : table: V_TEST owner: SYSDBA
STDOUT: 13: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 13: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8
STDOUT: : name: +4294967296(a) alias: +4294967296(a) : name: +4294967296(a) alias: +4294967296(a)
STDOUT: : table: V_TEST owner: SYSDBA : table: V_TEST owner: SYSDBA
STDOUT: 14: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 14: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8
STDOUT: : name: +4294967296(b) alias: +4294967296(b) : name: +4294967296(b) alias: +4294967296(b)
STDOUT: : table: V_TEST owner: SYSDBA : table: V_TEST owner: SYSDBA
STDOUT: 15: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 15: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8
STDOUT: : name: 9223372036854775807 alias: 9223372036854775807 : name: 9223372036854775807 alias: 9223372036854775807
STDOUT: : table: V_TEST owner: SYSDBA : table: V_TEST owner: SYSDBA
STDOUT: 16: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 16: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8
STDOUT: : name: -9223372036854775808 alias: -9223372036854775808 : name: -9223372036854775808 alias: -9223372036854775808
STDOUT: : table: V_TEST owner: SYSDBA : table: V_TEST owner: SYSDBA
STDOUT: 17: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 17: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8
STDOUT: : name: -9223372036854775807 alias: -9223372036854775807 : name: -9223372036854775807 alias: -9223372036854775807
STDOUT: : table: V_TEST owner: SYSDBA : table: V_TEST owner: SYSDBA
STDOUT: 18: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 18: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8
STDOUT: : name: -9223372036854775806 alias: -9223372036854775806 : name: -9223372036854775806 alias: -9223372036854775806
STDOUT: : table: V_TEST owner: SYSDBA : table: V_TEST owner: SYSDBA
STDOUT: 19: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8 19: sqltype: 580 INT64 Nullable scale: 0 subtype: 0 len: 8
STDOUT: : name: -1(c) alias: -1(c) : name: -1(c) alias: -1(c)
STDOUT: : table: V_TEST owner: SYSDBA : table: V_TEST owner: SYSDBA
"""
STDERR: Statement failed, SQLSTATE = 42000 expected_stderr_1 = """
STDERR: Dynamic SQL Error Statement failed, SQLSTATE = 42000
STDERR: -SQL error code = -104 Dynamic SQL Error
STDERR: -Token unknown - line 1, column 9 -SQL error code = -104
STDERR: -'1' -Token unknown - line 1, column 9
-'1'
STDERR: Statement failed, SQLSTATE = 42000 Statement failed, SQLSTATE = 42000
STDERR: Dynamic SQL Error Dynamic SQL Error
STDERR: -SQL error code = -104 -SQL error code = -104
STDERR: -Token unknown - line 1, column 9 -Token unknown - line 1, column 9
STDERR: -'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678x' -'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678x'
""" """
@pytest.mark.version('>=3.0') @pytest.mark.version('>=3.0')
@pytest.mark.xfail def test_1(act_1: Action):
def test_1(db_1): act_1.expected_stdout = expected_stdout_1
pytest.fail("Test not IMPLEMENTED") act_1.expected_stderr = expected_stderr_1
act_1.execute()
assert act_1.clean_stdout == act_1.clean_expected_stdout
assert act_1.clean_stderr == act_1.clean_expected_stderr

View File

@ -24,12 +24,13 @@
# qmid: bugs.core_1845 # qmid: bugs.core_1845
import pytest import pytest
from firebird.qa import db_factory, isql_act, Action from firebird.qa import db_factory, python_act, Action, user_factory, User
from firebird.driver import DatabaseError
# version: 2.5 # version: 2.5
# resources: None # resources: None
substitutions_1 = [('SERVER VERSION:.*', 'SERVER VERSION:'), ('SERVER IMPLEMENTATION:.*', 'SERVER IMPLEMENTATION:'), ('SERVICE MANAGER VERSION:.*', 'SERVICE MANAGER VERSION:'), ('Statement failed, SQLSTATE = HY000', ''), ('record not found for user.*', '')] substitutions_1 = []
init_script_1 = """""" init_script_1 = """"""
@ -133,31 +134,22 @@ 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 = """ act_1 = python_act('db_1', substitutions=substitutions_1)
WHO_AM_I TMP$C1845
CHECK SERVICE 'INFO_SERVER_VERSION': user_1 = user_factory(name='TMP$C1845', password='QweRtyUi')
SERVER VERSION: WI-V3.0.0.32266 FIREBIRD 3.0 RELEASE CANDIDATE 2
CHECK SERVICE 'INFO_IMPLEMENTATION':
SERVER IMPLEMENTATION: FIREBIRD/WINDOWS/INTEL/I386
CHECK SERVICE 'INFO_USER_DBPATH':
SERVICE ISC_INFO_SVC_USER_DBPATH REQUIRES SYSDBA PERMISSIONS. REATTACH TO THE SERVICE MANAGER USING THE SYSDBA ACCOUNT.
CHECK SERVICE 'INFO_GET_ENV':
SERVICE ISC_INFO_SVC_GET_ENV REQUIRES SYSDBA PERMISSIONS. REATTACH TO THE SERVICE MANAGER USING THE SYSDBA ACCOUNT.
CHECK SERVICE 'INFO_GET_ENV_LOCK':
SERVICE ISC_INFO_SVC_GET_ENV REQUIRES SYSDBA PERMISSIONS. REATTACH TO THE SERVICE MANAGER USING THE SYSDBA ACCOUNT.
CHECK SERVICE 'INFO_GET_ENV_MSG':
SERVICE ISC_INFO_SVC_GET_ENV REQUIRES SYSDBA PERMISSIONS. REATTACH TO THE SERVICE MANAGER USING THE SYSDBA ACCOUNT.
CHECK SERVICE 'INFO_SVR_DB_INFO':
SERVICE ISC_INFO_SVC_SVR_DB_INFO REQUIRES SYSDBA PERMISSIONS. REATTACH TO THE SERVICE MANAGER USING THE SYSDBA ACCOUNT.
CHECK SERVICE 'INFO_VERSION':
SERVICE MANAGER VERSION: 2
"""
@pytest.mark.version('>=2.5') @pytest.mark.version('>=2.5')
@pytest.mark.xfail def test_1(act_1: Action, user_1: User):
def test_1(db_1): with act_1.connect_server(user=user_1.name, password=user_1.password) as srv:
pytest.fail("Test not IMPLEMENTED") with pytest.raises(DatabaseError, match='.*requires SYSDBA permissions.*'):
print(srv.info.security_database)
with pytest.raises(DatabaseError, match='.*requires SYSDBA permissions.*'):
print(srv.info.home_directory)
with pytest.raises(DatabaseError, match='.*requires SYSDBA permissions.*'):
print(srv.info.lock_directory)
with pytest.raises(DatabaseError, match='.*requires SYSDBA permissions.*'):
print(srv.info.message_directory)
with pytest.raises(DatabaseError, match='.*requires SYSDBA permissions.*'):
print(srv.info.attached_databases)

View File

@ -19,14 +19,22 @@
# qmid: None # qmid: None
import pytest 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: 2.0 # version: 2.0
# resources: None # resources: None
substitutions_1 = [] substitutions_1 = []
init_script_1 = """""" init_script_1 = """
create table tmain(id int);
create table tdetl( id int, pid int, cost numeric(12,2) );
alter table tmain
add dsum2 computed by ( (select sum(cost) from tdetl d where d.pid = tmain.id) ) ;
commit;
"""
db_1 = db_factory(sql_dialect=3, init=init_script_1) db_1 = db_factory(sql_dialect=3, init=init_script_1)
@ -76,12 +84,16 @@ 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.0') @pytest.mark.version('>=2.0')
@pytest.mark.xfail def test_1(act_1: Action):
def test_1(db_1): backup = BytesIO()
pytest.fail("Test not IMPLEMENTED") with act_1.connect_server() as srv:
srv.database.local_backup(database=str(act_1.db.db_path), backup_stream=backup)
backup.seek(0)
# test fails if restore raises an exception
srv.database.local_restore(backup_stream=backup, database=str(act_1.db.db_path),
flags=SrvRestoreFlag.ONE_AT_A_TIME | SrvRestoreFlag.REPLACE)

View File

@ -9,7 +9,7 @@
# qmid: bugs.core_1926 # qmid: bugs.core_1926
import pytest import pytest
from firebird.qa import db_factory, isql_act, Action from firebird.qa import db_factory, python_act, Action
# version: 2.1.2 # version: 2.1.2
# resources: None # resources: None
@ -37,14 +37,21 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1)
# print (j-i) # print (j-i)
# con_detail.commit() # con_detail.commit()
#--- #---
#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1)
expected_stdout_1 = """1 act_1 = python_act('db_1', substitutions=substitutions_1)
"""
@pytest.mark.version('>=2.1.2') @pytest.mark.version('>=2.1.2')
@pytest.mark.xfail def test_1(act_1: Action):
def test_1(db_1): with act_1.db.connect() as con:
pytest.fail("Test not IMPLEMENTED") c = con.cursor()
c.execute('SELECT 1 FROM RDB$DATABASE')
with act_1.db.connect() as con_detail:
con_detail.begin()
c_detail = con_detail.cursor()
c_detail.execute("select MON$NEXT_TRANSACTION from MON$DATABASE")
tra_1 = c_detail.fetchone()[0]
con_detail.commit()
c_detail.execute("select MON$NEXT_TRANSACTION from MON$DATABASE")
tra_2 = c_detail.fetchone()[0]
con_detail.commit()
assert tra_2 - tra_1 == 1

View File

@ -5,7 +5,7 @@
# decription: # decription:
# We create common user using Services API and try to establish TWO subsequent connections under his login: # We create common user using Services API and try to establish TWO subsequent connections under his login:
# 1) with flag 'forced_write' = 1 and then # 1) with flag 'forced_write' = 1 and then
# 2) with flad 'no_reserve' = 1. # 2) with flag 'no_reserve' = 1.
# Note: both values of these flags have to be equal 1 because of some specifics of DPB building inside fdb driver: # Note: both values of these flags have to be equal 1 because of some specifics of DPB building inside fdb driver:
# value 0 means 'nothing to add', so no error will be raised in this case (and we DO expect error in this ticket). # value 0 means 'nothing to add', so no error will be raised in this case (and we DO expect error in this ticket).
# In WI-V2.1.1.17910 one may to specify *ANY* values of these flags and NO error will be raised. # In WI-V2.1.1.17910 one may to specify *ANY* values of these flags and NO error will be raised.
@ -33,7 +33,8 @@
# qmid: None # qmid: None
import pytest import pytest
from firebird.qa import db_factory, isql_act, Action from firebird.qa import db_factory, python_act, Action, user_factory, User
from firebird.driver import driver_config, connect
# version: 2.1.1 # version: 2.1.1
# resources: None # resources: None
@ -116,7 +117,8 @@ 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 = """ expected_stdout_1 = """
Successfully added non-privileged user Successfully added non-privileged user
@ -131,9 +133,23 @@ expected_stdout_1 = """
Successfully finished script Successfully finished script
""" """
user_1 = user_factory(name='TMP$C1972', password='123')
@pytest.mark.version('>=2.1.1') @pytest.mark.version('>=2.1.1')
@pytest.mark.xfail @pytest.mark.xfail
def test_1(db_1): def test_1(act_1: Action, user_1: User):
pytest.fail("Test not IMPLEMENTED") pytest.fail("Test not IMPLEMENTED")
# This test is not possible to implement with new Python driver as it does not
# allow to specify `forced_writes` or `reserve_space` options on connect() as tested
# configuration options are passed to DPB only for create_database()!
# This is intentional change in firebird-driver from fdb, as using these DPB options
# on connect has side-effects (changes database option) which was considered dangerous.
#
# 1. Try to specifying 'force_write' flag: no errors and NO changes in 2.1.1; error in 2.1.2 and above
act_1.db._make_config(user=user_1.name, password=user_1.password)
db_conf = driver_config.get_database('pytest')
db_conf.forced_writes.value = True
with pytest.raises():
connect('pytest')
# 2. Try to specifying 'no_reserve' flag: no errors and NO changes in 2.1.1; error in 2.1.2 and above

View File

@ -35,7 +35,8 @@
# qmid: None # qmid: None
import pytest import pytest
from firebird.qa import db_factory, isql_act, Action from firebird.qa import db_factory, python_act, Action, temp_file
from firebird.driver import SrvBackupFlag, SrvRestoreFlag
# version: 3.0.5 # version: 3.0.5
# resources: None # resources: None
@ -208,16 +209,47 @@ 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 = """ act_1 = python_act('db_1', substitutions=substitutions_1)
bkp: rows_without_stat=1
res: rows_without_stat=2 file_1 = temp_file('pytest-run.fbk')
"""
@pytest.mark.version('>=3.0.5') @pytest.mark.version('>=3.0.5')
@pytest.mark.xfail def test_1(act_1: Action, file_1):
def test_1(db_1): src_backup = act_1.vars['backups'] / 'core1999_30.fbk'
pytest.fail("Test not IMPLEMENTED") with act_1.connect_server() as srv:
srv.database.restore(database=str(act_1.db.db_path), backup=str(src_backup),
flags=SrvRestoreFlag.REPLACE,
verbose=True, stats='TDWR')
restore_log = srv.readlines()
srv.database.backup(database=str(act_1.db.db_path), backup=str(file_1),
verbose=True, stats='TDWR')
backup_log = srv.readlines()
#
# Backup log should contain SINGLE row without statistics, in its header (1st line):
# gbak: time delta reads writes
#
rows_without_stat = 0
for line in backup_log:
tokens = line.split()
if not (tokens[1].replace('.', '', 1).replace(',', '', 1).isdigit() and
tokens[2].replace('.', '', 1).replace(',', '', 1).isdigit() and
tokens[3].replace('.', '', 1).replace(',', '', 1).isdigit() and
tokens[4].replace('.', '', 1).replace(',', '', 1).isdigit()):
rows_without_stat = rows_without_stat + 1
assert rows_without_stat == 1
#
# Restore log should contain TWO rows without statistics, first and last:
# gbak: time delta reads writes
# gbak:adjusting the ONLINE and FORCED WRITES flags
#
rows_without_stat = 0
for line in restore_log:
tokens = line.split()
if not (tokens[1].replace('.', '', 1).replace(',', '', 1).isdigit() and
tokens[2].replace('.', '', 1).replace(',', '', 1).isdigit() and
tokens[3].replace('.', '', 1).replace(',', '', 1).isdigit() and
tokens[4].replace('.', '', 1).replace(',', '', 1).isdigit()):
rows_without_stat = rows_without_stat + 1
assert rows_without_stat == 2

View File

@ -25,12 +25,13 @@
# qmid: None # qmid: None
import pytest import pytest
from firebird.qa import db_factory, isql_act, Action from firebird.qa import db_factory, python_act, Action, user_factory, User
# version: 3.0 # version: 3.0
# resources: None # resources: None
substitutions_1 = [('Use CONNECT or CREATE DATABASE.*', ''), ('.*After line.*', '')] substitutions_1 = [('Use CONNECT or CREATE DATABASE.*', ''),
('.*After line.*', '')]
init_script_1 = """ init_script_1 = """
create or alter view v_check as create or alter view v_check as
@ -179,40 +180,103 @@ 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)
user_1 = user_factory(name='tmp$c2004_foo', password='123')
user_2 = user_factory(name='tmp$c2004_bar', password='456')
expected_stdout_1 = """ expected_stdout_1 = """
STDLOG: MSG init_state MSG init_state
STDLOG: SEC$USER_NAME TMP$C2004_FOO SEC$USER_NAME TMP$C2004_FOO
STDLOG: SEC$ACTIVE <false> SEC$ACTIVE <false>
STDLOG: SEC$PLUGIN Srp SEC$PLUGIN Srp
STDLOG: MSG init_state MSG init_state
STDLOG: SEC$USER_NAME TMP$C2004_BAR SEC$USER_NAME TMP$C2004_BAR
STDLOG: SEC$ACTIVE <false> SEC$ACTIVE <false>
STDLOG: SEC$PLUGIN Srp SEC$PLUGIN Srp
STDLOG: Records affected: 2 Records affected: 2
STDLOG: MSG try to connect as INACTIVE users MSG try to connect as INACTIVE users
STDLOG: MSG try to connect as user FOO which was just set as active by SYSDBA. MSG try to connect as user FOO which was just set as active by SYSDBA.
STDLOG: WHO_AM_I TMP$C2004_FOO WHO_AM_I TMP$C2004_FOO
STDLOG: WHATS_MY_ROLE RDB$ADMIN WHATS_MY_ROLE RDB$ADMIN
STDLOG: MSG try to connect as user BAR which was just set as active by FOO. MSG try to connect as user BAR which was just set as active by FOO.
STDLOG: WHO_AM_I TMP$C2004_BAR WHO_AM_I TMP$C2004_BAR
STDLOG: MSG try to drop both non-privileged users by SYSDBA. """
STDLOG: MSG final_state
STDLOG: SEC$USER_NAME <null> expected_stderr_1 = """
STDLOG: SEC$ACTIVE <null> Statement failed, SQLSTATE = 28000
STDLOG: SEC$PLUGIN <null> Your user name and password are not defined. Ask your database administrator to set up a Firebird login.
STDLOG: Records affected: 1 Statement failed, SQLSTATE = 28000
STDERR: Statement failed, SQLSTATE = 28000 Your user name and password are not defined. Ask your database administrator to set up a Firebird login.
STDERR: Your user name and password are not defined. Ask your database administrator to set up a Firebird login. After line 19 in file tmp_check_2004.sql
STDERR: Statement failed, SQLSTATE = 28000 """
STDERR: Your user name and password are not defined. Ask your database administrator to set up a Firebird login.
STDERR: After line 19 in file C:\\MIX irebird\\QA bt-repo mp mp_check_2004.sql
"""
@pytest.mark.version('>=3.0') @pytest.mark.version('>=3.0')
@pytest.mark.xfail def test_1(act_1: Action, user_1: User, user_2: User):
def test_1(db_1): act_1.script = f'''
pytest.fail("Test not IMPLEMENTED") set list on;
commit;
create or alter user tmp$c2004_foo password '123' inactive using plugin Srp grant admin role;
-- NB: currently it seems strange that one need to grant rdb$admin to 'foo'
-- For what reason this role need to be added if 'foo' does his actions only in security_db ?
-- Sent letter to dimitr and alex, 10-mar-18 16:00
grant rdb$admin to tmp$c2004_foo;
create or alter user tmp$c2004_bar password '456' inactive using plugin Srp;
commit;
set count on;
select 'init_state' as msg, v.* from v_check v;
set count off;
select 'try to connect as INACTIVE users' as msg from rdb$database;
commit;
connect '{act_1.db.dsn}' user tmp$c2004_foo password '123'; -- should fail
select current_user as who_am_i from rdb$database;
rollback;
connect '{act_1.db.dsn}' user tmp$c2004_bar password '456'; -- should fail
select current_user as who_am_i from rdb$database;
rollback;
connect '{act_1.db.dsn}' user SYSDBA password 'masterkey';
-- NB: following "alter user" statement must contain "using plugin Srp" clause
-- otherwise get:
-- Statement failed, SQLSTATE = HY000
-- record not found for user: TMP$C2004_BAR
alter user tmp$c2004_foo active using plugin Srp;
select 'try to connect as user FOO which was just set as active by SYSDBA.' as msg from rdb$database;
commit;
connect '{act_1.db.dsn}' user tmp$c2004_foo password '123' role 'RDB$ADMIN'; -- should pass
select current_user as who_am_i, current_role as whats_my_role from rdb$database;
-- should pass because foo has admin role:
create or alter user tmp$c2004_rio password '123' using plugin Srp;
drop user tmp$c2004_rio using plugin Srp;
-- should pass because foo has admin role:
alter user tmp$c2004_bar active using plugin Srp;
select 'try to connect as user BAR which was just set as active by FOO.' as msg from rdb$database;
commit;
connect '{act_1.db.dsn}' user tmp$c2004_bar password '456'; -- should pass
select current_user as who_am_i from rdb$database;
commit;
'''
act_1.expected_stdout = expected_stdout_1
act_1.expected_stderr = expected_stderr_1
act_1.execute()
assert act_1.clean_stderr == act_1.clean_expected_stderr
assert act_1.clean_stdout == act_1.clean_expected_stdout

View File

@ -23,7 +23,7 @@
# qmid: None # qmid: None
import pytest import pytest
from firebird.qa import db_factory, isql_act, Action from firebird.qa import db_factory, python_act, Action
# version: 2.5.7 # version: 2.5.7
# resources: None # resources: None
@ -117,15 +117,37 @@ db_1 = db_factory(page_size=4096, sql_dialect=3, init=init_script_1)
# # BEFORE 3.0.2.32641: (202472, 'select * from sp_test', '3.0.0') // after: 104942 # # BEFORE 3.0.2.32641: (202472, 'select * from sp_test', '3.0.0') // after: 104942
# # BEFORE 4.0.0.459: (202472, 'select * from sp_test', '4.0.0') // after: 104942 # # BEFORE 4.0.0.459: (202472, 'select * from sp_test', '4.0.0') // after: 104942
#--- #---
#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1)
act_1 = python_act('db_1', substitutions=substitutions_1)
expected_stdout_1 = """ expected_stdout_1 = """
IO statistics for procedure is OK IO statistics for procedure is OK
""" """
@pytest.mark.version('>=2.5.7') @pytest.mark.version('>=2.5.7')
@pytest.mark.xfail def test_1(act_1: Action, capsys):
def test_1(db_1): sp_query = 'select * from sp_test'
pytest.fail("Test not IMPLEMENTED") sql_io = '''
select
iif( i.mon$page_fetches > 104500, 'IO statistics for procedure is OK',
'Strange low value for fetches: ' || i.mon$page_fetches
) as fetches_result
from rdb$database r
left join mon$statements m on
m.mon$sql_text containing 'select * from sp_test'
and m.mon$sql_text NOT containing 'mon$statements'
left join mon$io_stats i on
m.mon$stat_id = i.mon$stat_id and i.mon$stat_group = 3
;
'''
act_1.expected_stdout = expected_stdout_1
with act_1.db.connect() as con:
stt1 = con.cursor()
stt2 = con.cursor()
stt2.execute(sp_query)
stt2.fetchall()
stt1.execute(sql_io)
for row in stt1:
print(row[0])
act_1.stdout = capsys.readouterr().out
assert act_1.clean_stdout == act_1.clean_expected_stdout

View File

@ -15,6 +15,7 @@
import pytest import pytest
from firebird.qa import db_factory, isql_act, Action from firebird.qa import db_factory, isql_act, Action
from firebird.driver import DbAccessMode
# version: 2.5 # version: 2.5
# resources: None # resources: None
@ -53,22 +54,44 @@ db_1 = db_factory(charset='ISO8859_1', sql_dialect=3, init=init_script_1)
# #
# #
#--- #---
#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1)
expected_stdout_1 = """ test_script_1 = """
MON$READ_ONLY 0 set list on;
RDB$FIELD_NAME X set blob all;
default 0 select mon$read_only from mon$database;
Records affected: 1 set count on;
MON$READ_ONLY 1 select RDB$FIELD_NAME, rdb$default_source from rdb$relation_fields
RDB$FIELD_NAME X where rdb$default_source is not null;
default 0 """
Records affected: 1
""" act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1)
expected_stdout_1_a = """
MON$READ_ONLY 0
RDB$FIELD_NAME X
default 0
Records affected: 1
"""
expected_stdout_1_b = """
MON$READ_ONLY 1
RDB$FIELD_NAME X
default 0
Records affected: 1
"""
@pytest.mark.version('>=2.5') @pytest.mark.version('>=2.5')
@pytest.mark.xfail def test_1(act_1: Action):
def test_1(db_1): act_1.expected_stdout = expected_stdout_1_a
pytest.fail("Test not IMPLEMENTED") act_1.execute()
assert act_1.clean_stdout == act_1.clean_expected_stdout
#
with act_1.connect_server() as srv:
srv.database.set_access_mode(database=str(act_1.db.db_path), mode=DbAccessMode.READ_ONLY)
#
act_1.reset()
act_1.expected_stdout = expected_stdout_1_b
act_1.isql(switches=[], charset='iso8859_1', input=act_1.script)
assert act_1.clean_stdout == act_1.clean_expected_stdout

View File

@ -9,7 +9,8 @@
# qmid: None # qmid: None
import pytest import pytest
from firebird.qa import db_factory, isql_act, Action from zipfile import Path
from firebird.qa import db_factory, python_act, Action
# version: 3.0 # version: 3.0
# resources: None # resources: None
@ -178,15 +179,17 @@ 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 = """ act_1 = python_act('db_1', substitutions=substitutions_1)
Current plans match to original ones.
"""
@pytest.mark.version('>=3.0') @pytest.mark.version('>=3.0')
@pytest.mark.xfail def test_1(act_1: Action):
def test_1(db_1): # Read script and expected stdout from zip file
pytest.fail("Test not IMPLEMENTED") datafile = Path(act_1.vars['files'] / 'core_2115.zip',
at='tmp_core_2115_queries_with_long_plans.sql')
act_1.script = datafile.read_text()
datafile = Path(act_1.vars['files'] / 'core_2115.zip',
at='tmp_core_2115_check_txt_of_long_plans.log')
act_1.expected_stdout = datafile.read_text()
act_1.execute()
assert act_1.clean_stdout == act_1.clean_expected_stdout

View File

@ -24,16 +24,50 @@
# qmid: None # qmid: None
import pytest import pytest
from firebird.qa import db_factory, isql_act, Action from firebird.qa import db_factory, python_act, Action
from firebird.driver import DbWriteMode, SrvRestoreFlag
#from difflib import unified_diff
from io import BytesIO
# version: 4.0 # version: 4.0
# resources: None # resources: None
substitutions_1 = [] substitutions_1 = []
init_script_1 = """""" test_size = 32768 # -- Ran 1 tests in 4.504s
# test_size = 16384 # -- Ran 1 tests in 2.735s
max_indx1 = int(test_size / 4 - 9)
max_indx6 = int(max_indx1 / 6)
max_indx8 = int(max_indx1 / 8)
db_1 = db_factory(sql_dialect=3, init=init_script_1) init_script_1 = f"""
set list on;
set bail on;
set echo on;
create sequence g;
commit;
create collation utf8_ci for utf8 from unicode case insensitive;
create collation utf8_ai_ci for utf8 from unicode accent insensitive case insensitive ;
commit;
create domain dm_non_coll as varchar({max_indx1});
create domain dm_collated_ci as varchar({max_indx6}) character set utf8 collate utf8_ci;
create domain dm_collated_ai_ci as varchar({max_indx6}) character set utf8 collate utf8_ai_ci;
commit;
recreate table test_non_coll(
txt_non_coll dm_non_coll
);
recreate table test_collated(
txt_ci dm_collated_ci
,txt_ai_ci dm_collated_ai_ci
);
commit;
create index test_non_coll on test_non_coll(txt_non_coll);
create index test_coll_ci on test_collated(txt_ci);
create index test_coll_ai_ci on test_collated(txt_ai_ci);
commit;
"""
db_1 = db_factory(sql_dialect=3, init=init_script_1, page_size=32784)
# test_script_1 # test_script_1
#--- #---
@ -384,12 +418,150 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1)
# #
# #
#--- #---
#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1)
test_script_1 = f'''
--show version;
delete from test_non_coll;
delete from test_collated;
commit;
set count on;
insert into test_non_coll(txt_non_coll)
select
rpad('', {max_indx1}, 'QWERTY' || gen_id(g,1) )
from
-- rdb$types rows 10000
(select 1 i from rdb$types rows 200), (select 1 i from rdb$types rows 5)
rows 361
;
commit;
insert into test_collated(txt_ci, txt_ai_ci)
select
rpad('', {max_indx6}, 'Ещё Съешь Этих Мягких Французских Булочек Да Выпей Же Чаю')
,rpad('', {max_indx6}, 'Ещё Французских Булочек Этих Мягких Съешь Да Чаю Выпей Же')
from
(select 1 i from rdb$types rows 250), (select 1 i from rdb$types rows 2)
;
commit;
set count off;
set list on;
set plan on;
select count(*)
from test_non_coll
where txt_non_coll starting with 'QWERTY'
union all
select count(*)
from test_collated
where txt_ci starting with 'еЩё'
union all
select count(*)
from test_collated
where txt_ai_ci starting with 'ёЩЕ'
union all
select count(*)
from test_collated
where txt_ci = lower(rpad('', {max_indx6}, 'Ещё Съешь Этих Мягких Французских Булочек Да Выпей Же Чаю'))
union all
select count(*)
from test_collated
where txt_ai_ci = rpad('', {max_indx6}, 'Ещё Французских Булочек Этих Мягких Съешь Да Чаю Выпей Же')
;
select count(*)
from test_non_coll
where txt_non_coll like 'QWERTY%%'
union all
select count(*)
from test_collated
where txt_ci like 'еЩё%%'
union all
select count(*)
from test_collated
where txt_ai_ci like 'ёЩЕ%%'
union all
select count(*)
from test_collated
where txt_ci between
rpad('', {max_indx6}, 'ещё Съешь ЭТИХ Мягких Французских Булочек Да Выпей Же Чаю')
and
rpad('', {max_indx6}, 'ЕЩЁ Съешь Этих МЯГКИХ фРанцузских Булочек Да Выпей Же Чаю')
union all
select count(*)
from test_collated
where txt_ai_ci between
rpad('', {max_indx6}, 'ёще фРанцузских Булочек Этих Мягких Съешь Да Чаю Выпёй Же')
and
rpad('', {max_indx6}, 'ёщё Французских Булочёк Этих Мягких Съёшь Да Чаю Выпёй Жё')
;
set plan off;
'''
act_1 = python_act('db_1', substitutions=substitutions_1)
@pytest.mark.version('>=4.0') @pytest.mark.version('>=4.0')
@pytest.mark.xfail def test_1(act_1: Action):
def test_1(db_1): # CHANGE FW to OFF
pytest.fail("Test not IMPLEMENTED") with act_1.connect_server() as srv:
srv.database.set_write_mode(database=str(act_1.db.db_path), mode=DbWriteMode.ASYNC)
# 1. FIRST RUN DML_TEST
act_1.script = test_script_1
act_1.execute()
run_dml_log_1 = act_1.stdout
# 2. EXTRACT METADATA-1
act_1.reset()
act_1.isql(switches=['-x'])
extract_meta1_sql = act_1.stdout
# 3. VALIDATE DATABASE-1
# [pcisar] I don't understand the point of validation as the original test does not check
# that validation passed
with act_1.connect_server() as srv:
srv.database.validate(database=str(act_1.db.db_path))
validate_log_1 = srv.readlines()
# 4. TRY TO BACKUP AND RESTORE
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)
backup.close()
# 5. EXTRACT METADATA-2
act_1.reset()
act_1.isql(switches=['-x'])
extract_meta2_sql = act_1.stdout
# 6. AGAIN RUN DML_TEST
act_1.reset()
act_1.script = test_script_1
act_1.execute()
run_dml_log_2 = act_1.stdout
# 7. VALIDATE DATABASE-2
with act_1.connect_server() as srv:
srv.database.validate(database=str(act_1.db.db_path))
validate_log_2 = srv.readlines()
# 8. CHECKS
# 1) STDERR for: create DB, backup, restore, validation-1 and validation-2 - they all must be EMPTY.
# [pcisar] This is granted as exception would be raised if there would be any error
# 2) diff between dml_1.log and dml_2.log should be EMPTY.
assert run_dml_log_1 == run_dml_log_2
# 3) diff between meta1.log and meta2.log should be EMPTY.
assert extract_meta1_sql == extract_meta2_sql

View File

@ -19,6 +19,8 @@
import pytest import pytest
from firebird.qa import db_factory, isql_act, Action from firebird.qa import db_factory, isql_act, Action
from io import BytesIO
from firebird.driver import SrvRestoreFlag, SrvBackupFlag
# version: 2.5 # version: 2.5
# resources: None # resources: None
@ -124,16 +126,49 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1)
# #
# #
#--- #---
#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1)
test_script_1 = '''
delete from log;
commit;
set term ^;
execute block as begin
rdb$set_context('USER_SESSION', 'INIT_STATE','1');
end
^
set term ;^
alter trigger trg_attach active;
alter trigger trg_detach active;
commit;
--set count on;
--select * from log;
'''
act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1)
expected_stdout_1 = """ expected_stdout_1 = """
Records affected: 0 Records affected: 0
Records affected: 0 """
"""
@pytest.mark.version('>=2.5') @pytest.mark.version('>=2.5')
@pytest.mark.xfail def test_1(act_1: Action):
def test_1(db_1): check_sql = 'set list on; set count on; select 1, g.* from log g;'
pytest.fail("Test not IMPLEMENTED") act_1.execute()
backup = BytesIO()
with act_1.connect_server() as srv:
srv.database.local_backup(database=str(act_1.db.db_path), backup_stream=backup,
flags=SrvBackupFlag.NO_TRIGGERS)
backup.seek(0)
act_1.reset()
act_1.expected_stdout = expected_stdout_1
act_1.isql(switches=['-nod'], input=check_sql)
assert act_1.clean_stdout == act_1.clean_expected_stdout
srv.database.local_restore(backup_stream=backup, database=str(act_1.db.db_path),
flags=SrvRestoreFlag.REPLACE)
backup.close()
act_1.reset()
act_1.expected_stdout = expected_stdout_1
act_1.isql(switches=['-nod'], input=check_sql)
assert act_1.clean_stdout == act_1.clean_expected_stdout