mirror of
https://github.com/FirebirdSQL/firebird-qa.git
synced 2025-01-22 21:43:06 +01:00
Added/Updated tests\bugs\gh_7772_test.py: Confirmed bug on 4.0.4.2997: restored database contains blob with size = 4464 which is less than initial size. Checked on 4.0.4.2998 -- all fine.
This commit is contained in:
parent
ee235a052a
commit
6cc0f067d3
115
tests/bugs/gh_7772_test.py
Normal file
115
tests/bugs/gh_7772_test.py
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
#coding:utf-8
|
||||||
|
|
||||||
|
"""
|
||||||
|
ID: issue-7772
|
||||||
|
ISSUE: https://github.com/FirebirdSQL/firebird/issues/7772
|
||||||
|
TITLE: Blob corruption in FB4.0.3 (embedded)
|
||||||
|
DESCRIPTION:
|
||||||
|
Problem appears when we use big streamed blobs with size 64K ... 128K.
|
||||||
|
Test creates table and fills it using BLOB_APPEND() function.
|
||||||
|
Then we do b/backup and make restore using embedded (local) mode.
|
||||||
|
Values of octet_length and hash for blob in restored DB must be unchanged.
|
||||||
|
NOTES:
|
||||||
|
[01.10.2023] pzotov
|
||||||
|
Thanks to Vlad for provided example for test.
|
||||||
|
Confirmed bug on 4.0.4.2997: restored database contains blob with size = 4464 which is less than initial size.
|
||||||
|
|
||||||
|
Checked on 4.0.4.2998 -- all fine.
|
||||||
|
::: NB :::
|
||||||
|
Currently FB 5.x and 6.x are also affected, so this test will FAIL on them.
|
||||||
|
Sent report to Vlad, 01.10.2023 09:50. Waiting for reply / fix in FB 5.x and 6.x
|
||||||
|
"""
|
||||||
|
from io import BytesIO
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from firebird.qa import *
|
||||||
|
from firebird.driver import SrvRestoreFlag
|
||||||
|
|
||||||
|
BLOB_DATA_LEN = 70000
|
||||||
|
init_sql = f"""
|
||||||
|
set term ^;
|
||||||
|
create table t_blb
|
||||||
|
(
|
||||||
|
id int
|
||||||
|
,blb blob sub_type text
|
||||||
|
) ^
|
||||||
|
commit ^
|
||||||
|
create or alter function gen_blb(asize int)
|
||||||
|
returns blob
|
||||||
|
as
|
||||||
|
declare b blob;
|
||||||
|
declare str varchar(36);
|
||||||
|
begin
|
||||||
|
str = uuid_to_char(gen_uuid());
|
||||||
|
while (asize > 0) do
|
||||||
|
begin
|
||||||
|
if (asize < 36) then
|
||||||
|
begin
|
||||||
|
str = substring(str from 1 for asize);
|
||||||
|
asize = 0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
asize = asize - 36;
|
||||||
|
|
||||||
|
b = blob_append(b, str);
|
||||||
|
end
|
||||||
|
return b;
|
||||||
|
end ^
|
||||||
|
commit ^
|
||||||
|
insert into t_blb values (1, gen_blb({BLOB_DATA_LEN})) ^
|
||||||
|
commit ^
|
||||||
|
"""
|
||||||
|
|
||||||
|
db = db_factory(init = init_sql)
|
||||||
|
act = python_act('db')
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def get_blob_octets_hash(act: Action):
|
||||||
|
blob_octets_len, blob_hash = -1, -1
|
||||||
|
with act.db.connect() as con:
|
||||||
|
cur = con.cursor()
|
||||||
|
#cur.execute('select octet_length(blb) from t_blb')
|
||||||
|
cur.execute('select octet_length(blb), crypt_hash(blb using sha512) from t_blb')
|
||||||
|
for r in cur:
|
||||||
|
blob_octets_len = r[0]
|
||||||
|
blob_hash = r[1]
|
||||||
|
# Convert binary to more readable view:
|
||||||
|
blob_hash = format(int.from_bytes(blob_hash, 'big'), 'x')
|
||||||
|
blob_hash = blob_hash.upper().rjust(128, '0')
|
||||||
|
|
||||||
|
return blob_octets_len, blob_hash
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@pytest.mark.version('>=4.0.4')
|
||||||
|
def test_1(act: Action, capsys):
|
||||||
|
|
||||||
|
init_len, init_hash = get_blob_octets_hash(act)
|
||||||
|
|
||||||
|
# backup + restore without creating .fbk:
|
||||||
|
#
|
||||||
|
bkp_data = BytesIO()
|
||||||
|
with act.connect_server() as srv:
|
||||||
|
srv.database.local_backup(database = act.db.db_path, backup_stream = bkp_data)
|
||||||
|
bkp_data.seek(0)
|
||||||
|
srv.database.local_restore(backup_stream = bkp_data, database = act.db.db_path, flags = SrvRestoreFlag.REPLACE)
|
||||||
|
|
||||||
|
curr_len, curr_hash = get_blob_octets_hash(act)
|
||||||
|
|
||||||
|
expected_stdout = "EXPECTED: blob data did not changed after backup-restore"
|
||||||
|
|
||||||
|
if init_len == curr_len and init_hash == curr_hash:
|
||||||
|
print(expected_stdout)
|
||||||
|
else:
|
||||||
|
print('UNEXPECTED: blob data CHANGED after backup-restore!')
|
||||||
|
print(f'Initial len: {init_len}')
|
||||||
|
print(f'Initial hash: {init_hash}')
|
||||||
|
print(f'Current len: {curr_len}')
|
||||||
|
print(f'Current hash: {curr_hash}')
|
||||||
|
|
||||||
|
act.expected_stdout = expected_stdout
|
||||||
|
act.stdout = capsys.readouterr().out
|
||||||
|
assert act.clean_stdout == act.clean_expected_stdout
|
||||||
|
act.reset()
|
Loading…
Reference in New Issue
Block a user