mirror of
https://github.com/FirebirdSQL/firebird-qa.git
synced 2025-01-22 13:33:07 +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