#coding:utf-8 """ ID: issue-2890 ISSUE: 2890 TITLE: mon$memory_usage: Sorting memory should be reported as owned by the statement DESCRIPTION: NOTES: [16.11.2021] pcisar This test is too complicated and fragile, and it's IMHO not worth to be implemented [24.07.2022] pzotov Test was totally re-implemented. No async call of ISQL, waiting/killing etc. Checked on 3.0.8.33535, 4.0.1.2692, 5.0.0.591 JIRA: CORE-2477 FBTEST: bugs.core_2477 """ import subprocess from pathlib import Path import pytest from firebird.qa import * import time MIN_DIFF_THRESHOLD=60000000 init_script = """ create or alter view v_mon as select * from ( select m.mon$stat_group as stat_gr ,rpad( decode(m.mon$stat_group, 0,'0:database', 1,'1:attachment', 2,'2:transaction', 3,'3:statement', 4,'4:call'), 15,' ') as stat_type ,m.mon$memory_used as memo_used ,m.mon$memory_allocated as memo_allo ,m.mon$max_memory_used as max_memo_used ,m.mon$max_memory_allocated as max_memo_allo ,m.mon$stat_id as stat_id ,coalesce( s.mon$attachment_id, t.mon$attachment_id, a.mon$attachment_id, -999 ) as att_id ,coalesce( s.mon$transaction_id, t.mon$transaction_id, -999 ) as trn_id ,coalesce( s.mon$statement_id, -999) as sttm_id ,coalesce( decode( s.mon$state, 0,'idle', 1,'running', 2,'stalled' ), 'n/a') as stm_state ,lower(right( coalesce(trim(coalesce(a.mon$remote_process, a.mon$user)), ''), 20 )) as att_process -- isql.exe or Garbage Collector or Cache Writer ,lower(left( coalesce(cast(s.mon$sql_text as varchar(8100)),''), 128 )) as sql_text from mon$memory_usage m left join mon$statements s on m.mon$stat_group = 3 and m.mon$stat_id = s.mon$stat_id left join mon$transactions t on m.mon$stat_group = 2 and m.mon$stat_id = t.mon$stat_id or m.mon$stat_group = 3 and m.mon$stat_id = s.mon$stat_id and t.mon$transaction_id = s.mon$transaction_id left join mon$attachments a on m.mon$stat_group = 1 and m.mon$stat_id = a.mon$stat_id or m.mon$stat_group=2 and m.mon$stat_id = t.mon$stat_id and a.mon$attachment_id = t.mon$attachment_id or m.mon$stat_group=3 and m.mon$stat_id = s.mon$stat_id and a.mon$attachment_id = s.mon$attachment_id ) t where t.stat_gr = 3 and sql_text containing 'HEAVY_SORT_TAG' order by stat_type, stat_id ; create or alter view v_gather_mon as select v.att_process ,replace(replace(replace(replace(v.sql_text, ascii_char(10),' '), ascii_char(13),' '),' ',' '),' ',' ') as sql_text ,v.stat_type ,v.stm_state ,v.att_id ,v.trn_id ,v.sttm_id ,v.memo_used ,v.memo_allo from v_mon v where v.att_id is distinct from current_connection ; commit; """ db = db_factory(init=init_script) act = python_act('db') def result_msg(a_diff_value, a_min_threshold): return ( ('OK, expected: increased significantly.') if a_diff_value > a_min_threshold else ('BAD! Did not increased as expected. Difference: ' + "{:d}".format(a_diff_value)+'.') ) @pytest.mark.version('>=3.0') def test_1(act: Action, capsys): heavy_sql_sttm = "select /* HEAVY_SORT_TAG */ distinct lpad('', 32500, uuid_to_char(gen_uuid())) s from (select 1 i from rdb$types rows 100) a, (select 1 i from rdb$types rows 100) b" map_result = {} with act.db.connect() as con_worker: cur_worker = con_worker.cursor() cur_wrk_ps = cur_worker.prepare(heavy_sql_sttm) for m in ('beg','end'): with act.db.connect() as con_monitor: cur_monitor=con_monitor.cursor() cur_monitor.execute('select * from v_gather_mon') for r in cur_monitor: map_result[m] = (r[3], r[7]) # ('idle' | 'stalled', memo_used) if m == 'beg': cur_worker.execute(cur_wrk_ps) for i in range(0, 5000): r = cur_worker.fetchone() # After this loop statement with huge sort will remain in stalled state # (its mon$statements.mon$state must be 2). # We can now gather mon$ info second time (in a NEW connection) # and then evaluate DIFFERENCE. #------------------------------------------------------------------------------------------ assert map_result['beg'][0].strip() == 'idle' and map_result['end'][0].strip() == 'stalled' expected_msg = 'DELTA of mon$memory_used increased significantly.' diff = map_result['end'][1] - map_result['beg'][1] if diff > MIN_DIFF_THRESHOLD: print(expected_msg) else: print('### FAIL ### DELTA of mon$memory_used increased for less than MIN_DIFF_THRESHOLD = %d' % MIN_DIFF_THRESHOLD) for k,v in sorted(map_result.items()): print(k,':',v) print('diff = %d' % diff) act.expected_stdout = expected_msg act.stdout = capsys.readouterr().out assert act.clean_stdout == act.clean_expected_stdout