mirror of
https://github.com/FirebirdSQL/firebird-qa.git
synced 2025-01-22 21:43:06 +01:00
Added/Updated bugs\core_4337_test.py. Removed check of sweep log: sometime it can remain empty, for unknown reason (detected on 4.0.1 Classic). Added loop with check for several seconds for appearance of 2nd gfix attach - as it was initially implemented in fbt.
This commit is contained in:
parent
6ebb2e3824
commit
49c162c060
@ -68,7 +68,7 @@ substitutions = [
|
|||||||
('FIREBIRD.LOG:.* ERROR DURING SWEEP OF .*TEST.FDB.*', 'FIREBIRD.LOG: + ERROR DURING SWEEP OF TEST.FDB')
|
('FIREBIRD.LOG:.* ERROR DURING SWEEP OF .*TEST.FDB.*', 'FIREBIRD.LOG: + ERROR DURING SWEEP OF TEST.FDB')
|
||||||
]
|
]
|
||||||
|
|
||||||
make_garbage = """
|
init_sql = """
|
||||||
set list on;
|
set list on;
|
||||||
recreate table t(
|
recreate table t(
|
||||||
s01 varchar(4000)
|
s01 varchar(4000)
|
||||||
@ -115,7 +115,7 @@ make_garbage = """
|
|||||||
# 16K page is neccessary ! Smaller size will cause failure with:
|
# 16K page is neccessary ! Smaller size will cause failure with:
|
||||||
# key size exceeds implementation restriction for index "T_S01"
|
# key size exceeds implementation restriction for index "T_S01"
|
||||||
#
|
#
|
||||||
db = db_factory(page_size=16384, init = make_garbage)
|
db = db_factory(page_size=16384, init = init_sql)
|
||||||
|
|
||||||
act = python_act('db', substitutions = substitutions)
|
act = python_act('db', substitutions = substitutions)
|
||||||
|
|
||||||
@ -143,10 +143,14 @@ def test_1(act: Action, sweep_log: Path, capsys):
|
|||||||
|
|
||||||
#---------------------------------------------------------------
|
#---------------------------------------------------------------
|
||||||
|
|
||||||
# How long can we wait for appearance of 'gfix' process in the mon$attachments, ms:
|
# How long can we wait (milliseconds) for the FIRST appearance of 'gfix' process in mon$attachments:
|
||||||
#
|
#
|
||||||
MAX_WAIT_FOR_SWEEP_START_MS = 3000
|
MAX_WAIT_FOR_SWEEP_START_MS = 3000
|
||||||
|
|
||||||
|
# How long we wait (milliseconds) for SECOND appearance of 'gfix' process in mon$attachments, after it was killed.
|
||||||
|
# NOTE. If it appears then we have a BUG
|
||||||
|
MAX_WAIT_FOR_GFIX_RESTART_MS = 3000
|
||||||
|
|
||||||
sweep_attach_id = None
|
sweep_attach_id = None
|
||||||
sweep_reconnect = None
|
sweep_reconnect = None
|
||||||
# Start trace
|
# Start trace
|
||||||
@ -157,7 +161,14 @@ def test_1(act: Action, sweep_log: Path, capsys):
|
|||||||
t1=py_dt.datetime.now()
|
t1=py_dt.datetime.now()
|
||||||
with con.cursor() as cur:
|
with con.cursor() as cur:
|
||||||
ps = cur.prepare(stm)
|
ps = cur.prepare(stm)
|
||||||
p_sweep = subprocess.Popen( [act.vars['gfix'], '-sweep', '-user', act.db.user, '-password', act.db.password, act.db.dsn], stdout = f_sweep_log, stderr = subprocess.STDOUT )
|
p_sweep = subprocess.Popen( [act.vars['gfix'], '-sweep', '-user', act.db.user, '-password', act.db.password, act.db.dsn],
|
||||||
|
stdout = f_sweep_log,
|
||||||
|
stderr = subprocess.STDOUT
|
||||||
|
)
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# LOOP-1: WAIT FOR FIRST APPEARANCE OF GFIX PROCESS IN THE MON$ATTACHMENTS
|
||||||
|
##########################################################################
|
||||||
while True:
|
while True:
|
||||||
t2=py_dt.datetime.now()
|
t2=py_dt.datetime.now()
|
||||||
d1=t2-t1
|
d1=t2-t1
|
||||||
@ -176,53 +187,83 @@ def test_1(act: Action, sweep_log: Path, capsys):
|
|||||||
else:
|
else:
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
#<while True (loop for search gfix process in mon$attachments)
|
#<while True (loop for search gfix process in mon$attachments)
|
||||||
|
|
||||||
#< with con.cursor() as cur
|
#< with con.cursor() as cur
|
||||||
|
|
||||||
#assert sweep_attach_id is None, f'attacment_id of SWEEP process is {sweep_attach_id}'
|
#assert sweep_attach_id is None, f'attacment_id of SWEEP process is {sweep_attach_id}'
|
||||||
assert sweep_attach_id, 'attacment_id of SWEEP process was not found.'
|
assert sweep_attach_id, 'attacment_id of SWEEP process was not found.'
|
||||||
|
|
||||||
|
# Let sweep to have some 'useful work':
|
||||||
|
#
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
# Now we can KILL attachment that belongs to SWEEP process, <sweep_attach_id>:
|
# Now we can KILL attachment that belongs to SWEEP process, <sweep_attach_id>:
|
||||||
con.execute_immediate(f'delete from mon$attachments where mon$attachment_id = {sweep_attach_id}')
|
con.execute_immediate(f'delete from mon$attachments where mon$attachment_id = {sweep_attach_id}')
|
||||||
|
|
||||||
p_sweep.wait()
|
p_sweep.wait()
|
||||||
f_sweep_log.close()
|
f_sweep_log.close()
|
||||||
|
|
||||||
con.commit()
|
assert p_sweep.returncode == 1, 'p_sweep.returncode: {p_sweep.returncode}'
|
||||||
|
|
||||||
|
|
||||||
|
##################################################################################################
|
||||||
|
# LOOP-2: WAIT FOR POSSIBLE SECOND APPEARENCE (RECONNECT) OF GFIX. IF IT OCCURS THEN WE HAVE A BUG
|
||||||
|
##################################################################################################
|
||||||
|
ps = cur.prepare( stm.replace('select ', 'select /* search re-connect that could be made */ ') )
|
||||||
|
t1=py_dt.datetime.now()
|
||||||
with con.cursor() as cur:
|
with con.cursor() as cur:
|
||||||
cur.execute( stm.replace('select ', 'select /* search re-connect that could be made */ ') )
|
while True:
|
||||||
|
t2=py_dt.datetime.now()
|
||||||
|
d1=t2-t1
|
||||||
|
dd = d1.seconds*1000 + d1.microseconds//1000
|
||||||
|
if dd > MAX_WAIT_FOR_GFIX_RESTART_MS:
|
||||||
|
# Expected: gfix reconnect was not detected for last {MAX_WAIT_FOR_GFIX_RESTART_MS} ms.
|
||||||
|
break
|
||||||
|
con.commit()
|
||||||
|
cur.execute(ps)
|
||||||
# Resultset now must be EMPTY. we must not find any record!
|
# Resultset now must be EMPTY. we must not find any record!
|
||||||
for r in cur:
|
for r in cur:
|
||||||
sweep_reconnect = r[0]
|
sweep_reconnect = r[0]
|
||||||
|
|
||||||
|
#con.commit()
|
||||||
|
if sweep_reconnect:
|
||||||
|
# UNEXPECTED: gfix reconnect found, with attach_id={sweep_reconnect}
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
assert sweep_reconnect is None, f'Found re-connect of SWEEP process, attachment: {sweep_reconnect}'
|
assert sweep_reconnect is None, f'Found re-connect of SWEEP process, attachment: {sweep_reconnect}'
|
||||||
|
|
||||||
#< with db.connect as con
|
#< with db.connect as con
|
||||||
|
|
||||||
time.sleep(1) # do NOT remove otherwise log of failed sweep can remain empty
|
|
||||||
|
|
||||||
#---------------------------------------------------------------
|
#---------------------------------------------------------------
|
||||||
# Check-1: log of sweep must contain text: 'connection shutdown':
|
# DISABLED 25.09.2022. SWEEP log can remain empty (4.0.1.2692 Classic)
|
||||||
for line in sweep_log.read_text().splitlines():
|
## Check-1: log of sweep must contain text: 'connection shutdown':
|
||||||
if line:
|
#for line in sweep_log.read_text().splitlines():
|
||||||
print('SWEEP LOG:', line.upper())
|
# if line:
|
||||||
|
# print('SWEEP LOG:', line.upper())
|
||||||
act.expected_stdout = 'sweep log: connection shutdown'.upper()
|
#
|
||||||
act.stdout = capsys.readouterr().out
|
#act.expected_stdout = 'sweep log: connection shutdown'.upper()
|
||||||
assert act.clean_stdout == act.clean_expected_stdout
|
#act.stdout = capsys.readouterr().out
|
||||||
act.reset()
|
#assert act.clean_stdout == act.clean_expected_stdout
|
||||||
|
#act.reset()
|
||||||
#---------------------------------------------------------------
|
#---------------------------------------------------------------
|
||||||
|
|
||||||
# Trace log
|
# Trace log
|
||||||
found_sweep_failed = 0
|
found_sweep_failed = 0
|
||||||
p_sweep_failed = re.compile( r'[.*\s+]*20\d{2}(-\d{2}){2}T\d{2}(:\d{2}){2}.\d{3,4}\s+\(.+\)\s+SWEEP_FAILED$', re.IGNORECASE)
|
p_sweep_failed = re.compile( r'[.*\s+]*20\d{2}(-\d{2}){2}T\d{2}(:\d{2}){2}.\d{3,4}\s+\(.+\)\s+SWEEP_FAILED$', re.IGNORECASE)
|
||||||
|
p_att_success = re.compile( r'[.*\s+]*20\d{2}(-\d{2}){2}T\d{2}(:\d{2}){2}.\d{3,4}\s+\(.+\)\s+ATTACH_DATABASE$', re.IGNORECASE)
|
||||||
|
|
||||||
trace_expected = 'FOUND SWEEP_FAILED MESSAGE.'
|
trace_expected = 'FOUND SWEEP_FAILED MESSAGE.'
|
||||||
for line in act.trace_log:
|
for i,line in enumerate(act.trace_log):
|
||||||
if line.strip():
|
if line.strip():
|
||||||
if p_sweep_failed.search(line.strip()):
|
if p_sweep_failed.search(line.strip()):
|
||||||
print(trace_expected)
|
print(trace_expected)
|
||||||
found_sweep_failed = 1
|
found_sweep_failed = 1
|
||||||
if found_sweep_failed == 1 and ('ATTACH_DATABASE' in line):
|
if found_sweep_failed == 1 and p_att_success.search(line) and i < len(act.trace_log)-2 and 'gfix' in act.trace_log[i+2].lower():
|
||||||
print('TRACE: ATTACH DETECTED AFTER SWEEP FAILED! ')
|
# NB: we have to ignore "FAILED ATTACH_DATABASE".
|
||||||
|
# It can occur in some cases.
|
||||||
|
print('TRACE: UNEXPECTED ATTACH FOUND AFTER KILL SWEEP! CHECK LINE N {i}:')
|
||||||
print('TRACE_LOG: ' + line)
|
print('TRACE_LOG: ' + line)
|
||||||
|
|
||||||
act.expected_stdout = trace_expected
|
act.expected_stdout = trace_expected
|
||||||
|
Loading…
Reference in New Issue
Block a user