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

167 lines
5.4 KiB
Python
Raw Normal View History

2021-04-26 20:07:00 +02:00
#coding:utf-8
#
# id: bugs.core_5210
# title: Firebird 3.0 + fbclient 3.0 - POST_EVENT won't work
2021-11-30 19:13:50 +01:00
# decription:
2021-04-26 20:07:00 +02:00
# We create database-level trigger which sends event with name 'dml_event' on COMMIT.
2021-11-30 19:13:50 +01:00
# Then we do new connect and run thread with INSERT statement (with delay = 1.0 second), and wait
2021-04-26 20:07:00 +02:00
# NO MORE than <max4delivering> sec.
2021-11-30 19:13:50 +01:00
# We should receive event during ~ 1.0 second.
2021-04-26 20:07:00 +02:00
# We have to consider result as FAIL if we do not receive event in <max4delivering> seconds.
# Result of "events.wait(max4delivering)" will be non-empty dictionary with following key-value:
# {'dml_event': 1} - when all fine and client got event;
# {'dml_event': 0} - when NO event was delivered
# All such actions are repeated several times in order to increase probability of failure if something
# in FB will be broken.
2021-11-30 19:13:50 +01:00
#
2021-04-26 20:07:00 +02:00
# Confirmed wrong result on: 4.0.0.145, V3.0.0.32493 - with probability approx 60%.
# All fine on: T4.0.0.150, WI-V3.0.0.32496 (SS/SC/CS).
2021-11-30 19:13:50 +01:00
#
# PS. Event handling code in this text was adapted from fdb manual:
2021-04-26 20:07:00 +02:00
# http://pythonhosted.org/fdb/usage-guide.html#database-events
2021-11-30 19:13:50 +01:00
#
2021-04-26 20:07:00 +02:00
# tracker_id: CORE-5210
# min_versions: ['2.5.6']
# versions: 2.5.6
# qmid: None
import pytest
2021-11-30 19:13:50 +01:00
from time import time
from threading import Timer
from firebird.qa import db_factory, python_act, Action
2021-04-26 20:07:00 +02:00
# version: 2.5.6
# resources: None
substitutions_1 = []
init_script_1 = """
set term ^;
create or alter trigger trg_commit on transaction commit as
begin
post_event 'dml_event';
end ^
set term ;^
commit;
recreate table test(id int);
commit;
2021-11-30 19:13:50 +01:00
"""
2021-04-26 20:07:00 +02:00
db_1 = db_factory(sql_dialect=3, init=init_script_1)
# test_script_1
#---
2021-11-30 19:13:50 +01:00
#
2021-04-26 20:07:00 +02:00
# def check_events(seqno):
# import fdb
# import threading
# import datetime
# import time
# from time import time
# import os
2021-11-30 19:13:50 +01:00
#
2021-04-26 20:07:00 +02:00
# os.environ["ISC_USER"] = user_name
# os.environ["ISC_PASSWORD"] = user_password
2021-11-30 19:13:50 +01:00
#
2021-04-26 20:07:00 +02:00
# # Utility function
# def send_events(command_list):
# cur=db_conn.cursor()
# for cmd in command_list:
# cur.execute(cmd)
# db_conn.commit()
2021-11-30 19:13:50 +01:00
#
2021-04-26 20:07:00 +02:00
# timed_event = threading.Timer(1.0, send_events, args=[["insert into test(id) values ( rand()*1000 )",]])
2021-11-30 19:13:50 +01:00
#
# # Connection.event_conduit() takes a sequence of string event names as parameter, and returns
2021-04-26 20:07:00 +02:00
# # EventConduit instance.
# events = db_conn.event_conduit(['dml_event'])
2021-11-30 19:13:50 +01:00
#
# # To start listening for events it's necessary (starting from FDB version 1.4.2)
2021-04-26 20:07:00 +02:00
# # to call EventConduit.begin() method or use EventConduit's context manager interface
2021-11-30 19:13:50 +01:00
# # Immediately when begin() method is called, EventConduit starts to accumulate notifications
# # of any events that occur within the conduit's internal queue until the conduit is closed
2021-04-26 20:07:00 +02:00
# # (via the close() method)
2021-11-30 19:13:50 +01:00
#
# #print("Start listening for event")
#
2021-04-26 20:07:00 +02:00
# events.begin()
2021-11-30 19:13:50 +01:00
#
2021-04-26 20:07:00 +02:00
# timed_event.start()
2021-11-30 19:13:50 +01:00
#
#
# # Notifications about events are aquired through call to wait() method, that blocks the calling
# # thread until at least one of the events occurs, or the specified timeout (if any) expires,
2021-04-26 20:07:00 +02:00
# # and returns None if the wait timed out, or a dictionary that maps event_name -> event_occurrence_count.
# #t1 = datetime.datetime.now()
# t1 = time()
# max4delivering = 3
# e = events.wait(max4delivering)
# t2 = time()
# #t2 = datetime.datetime.now()
2021-11-30 19:13:50 +01:00
#
#
2021-04-26 20:07:00 +02:00
# events.close()
2021-11-30 19:13:50 +01:00
#
2021-04-26 20:07:00 +02:00
# print(e)
# print( str(seqno)+': event was SUCCESSFULLY delivered.' if t2-t1 < max4delivering else str(seqno)+': event was NOT delivered for %.2f s (threshold is %.2f s)' % ( (t2-t1), max4delivering ) )
2021-11-30 19:13:50 +01:00
#
2021-04-26 20:07:00 +02:00
# check_events(1)
# check_events(2)
# check_events(3)
# check_events(4)
# check_events(5)
2021-11-30 19:13:50 +01:00
#
2021-04-26 20:07:00 +02:00
#---
2021-11-30 19:13:50 +01:00
act_1 = python_act('db_1', substitutions=substitutions_1)
2021-04-26 20:07:00 +02:00
expected_stdout_1 = """
{'dml_event': 1}
1: event was SUCCESSFULLY delivered.
{'dml_event': 1}
2: event was SUCCESSFULLY delivered.
{'dml_event': 1}
3: event was SUCCESSFULLY delivered.
{'dml_event': 1}
4: event was SUCCESSFULLY delivered.
{'dml_event': 1}
5: event was SUCCESSFULLY delivered.
2021-11-30 19:13:50 +01:00
"""
2021-04-26 20:07:00 +02:00
2021-11-30 19:13:50 +01:00
def send_events(con, command_list):
cur = con.cursor()
for cmd in command_list:
cur.execute(cmd)
con.commit()
2021-04-26 20:07:00 +02:00
2021-11-30 19:13:50 +01:00
@pytest.mark.version('>=2.5.6')
def test_1(act_1: Action, capsys):
def check_events(seqno: int):
with act_1.db.connect() as con:
timed_event = Timer(1.0, send_events, args=[con, ["insert into test(id) values (rand()*1000)",]])
with con.event_collector(['dml_event']) as events:
timed_event.start()
t1 = time()
max4delivering = 3
e = events.wait(max4delivering)
t2 = time()
print(e)
print(f'{seqno}: event was SUCCESSFULLY delivered.' if t2-t1 < max4delivering
else f'{seqno}: event was NOT delivered for {t2-t1}s (threshold is {max4delivering}s)')
2021-04-26 20:07:00 +02:00
2021-11-30 19:13:50 +01:00
#
check_events(1)
check_events(2)
check_events(3)
check_events(4)
check_events(5)
# Check
act_1.expected_stdout = expected_stdout_1
act_1.stdout = capsys.readouterr().out
assert act_1.clean_stdout == act_1.clean_expected_stdout