6
0
mirror of https://github.com/FirebirdSQL/firebird-qa.git synced 2025-01-23 05:53:06 +01:00
firebird-qa/tests/bugs/core_2493_test.py

292 lines
12 KiB
Python
Raw Normal View History

2021-04-26 20:07:00 +02:00
#coding:utf-8
2022-01-21 18:49:26 +01:00
"""
ID: issue-2906
ISSUE: 2906
TITLE: Append the IP address of the remote host to error messages in firebird.log for TCP connections
DESCRIPTION:
Following actions are performed by this test:
1. Obtain current firebird.log and saves it to the file with name = 'tmp_2493_fblog_before.txt';
2021-04-26 20:07:00 +02:00
2022-01-21 18:49:26 +01:00
2. Asynchronously launch ISQL in child process with request to return client IP address (via asking context variable)
and after this - do some 'heavy query' that for sure will take a lot of time and resources.
Output is redirected to file with name = 'tmp_2493_isql.log' and will be parsed further (we'll search for client IP there).
2021-04-26 20:07:00 +02:00
2022-01-21 18:49:26 +01:00
3. Kill launched ISQL process after several seconds. At this point new message must appear in firebird.log and it MUST
be in format described in the ticket. Because this abend will be detected by SERVER, format of message will be like this:
(for TCPv4): INET/inet_error: read errno = 10054, client host = prog1, address = 127.0.0.1/4076, user = john
(for TCPv6): INET/inet_error: read errno = 10054, client host = prog2, address = fe80::c40e:21ec:b5c7:8963/56831, user = mick
2021-04-26 20:07:00 +02:00
2022-01-21 18:49:26 +01:00
4. Wait several seconds and after it - obtain again firebird.log (new content) and save it in 'tmp_2493_fblog_after.txt'.
5. Make file comparison by calling method from standard Python tool - difflib. Result of this comparison will be stored
in file with name 'tmp_2493_diff.txt'. This file will have several lines from which we are interested only for one which
STARTS with "+" (PLUS sign) and does contain phrase 'INET/INET_ERROR'. Diff-file must contain only ONE such line.
6. Next we parse this line: remove "/" and "="characters from it and split then text into array of words:
+ INET inet_error read errno 10054 client host prog1 address 127.0.0.1 4417 user john ------- for IPv4
0 1 2 3 4 5 6 7 8 9 10 11 12 13
+ INET inet_error read errno 10054 client host prog2 address x::y:z:u:v 56831 user mick ------- for IPv6
7. Then we scan this array backward and check tokens for matching simple rules (N = array len):
* token N-1 must be OS user name; this name can be followed by some kind of "suffix": "JOHN.-1.-1" - and we have to take only 1st word from it.
NB: we current OS user using call of getpass.getuser(). It must be compared in case insensitive manner;
* token N-2 is just word "user" (as is);
* token N-3 is port number, it has to be positive value;
* token N-4 is IP. It must be equal to rdb$get_context('SYSTEM','CLIENT_ADDRESS').
This is how differences look in firebird.log:
# 2.5.9:
# INET/inet_error: read errno = 10054, client address = 127.0.0.1 3268, user ZOTOV.-1.-1
# ^ ^ ^ ^
# N-4 N-3 N-2 N-1
# 3.0.4:
# INET/inet_error: read errno = 10054, client host = csprog, address = 127.0.0.1 3298, user zotov
# ^ ^ ^ ^
# N-4 N-3 N-2 N-1
# 3.0.8 and 4.0.0 RC1:
# INET/inet_error: read errno = 10054, client host = csprog, address = fe80::fcf1:e33c:e924:969d%16/56887, user = zotov
# INET/inet_error: read errno = 10054, client host = csprog, address = fe80::fcf1:e33c:e924:969d%16/56883, user = zotov
NOTES:
[20.02.2021]
changed 'platform' attribute to Windows only. Content of firebird.log has no changes on Linux during this test run.
Perhaps, this is temporary and another solution will be found/implemented. Sent letter to dimitr et al, 21.02.2021 08:20.
JIRA: CORE-2493
FBTEST: bugs.core_2493
2022-01-21 18:49:26 +01:00
"""
import pytest
from firebird.qa import *
init_script = """
2021-04-26 20:07:00 +02:00
recreate table log(ip varchar(255));
create sequence g;
commit;
"""
2021-04-26 20:07:00 +02:00
2022-01-21 18:49:26 +01:00
db = db_factory(init=init_script)
act = python_act('db')
expected_stdout = """
String IP/port: valid, equal to 'CLIENT_ADDRESS'
Port value: valid, positive integer.
OS user: valid, passed getpass.getuser()
"""
2022-01-25 22:55:48 +01:00
@pytest.mark.skip('FIXME: Not IMPLEMENTED')
2022-01-21 18:49:26 +01:00
@pytest.mark.version('>=3')
@pytest.mark.platform('Windows')
def test_1(act: Action):
2022-01-25 22:55:48 +01:00
pytest.fail("Not IMPLEMENTED")
2022-01-21 18:49:26 +01:00
2021-04-26 20:07:00 +02:00
# test_script_1
#---
# import os
# import time
# import subprocess
# from subprocess import Popen
# import signal
# import difflib
# import re
# import socket
# import getpass
#
2021-04-26 20:07:00 +02:00
# os.environ["ISC_USER"] = user_name
# os.environ["ISC_PASSWORD"] = user_password
#
2021-04-26 20:07:00 +02:00
# engine = str(db_conn.engine_version)
# db_conn.close()
#
2021-04-26 20:07:00 +02:00
# #-----------------------------------
#
2021-04-26 20:07:00 +02:00
# def flush_and_close(file_handle):
# # https://docs.python.org/2/library/os.html#os.fsync
# # If you're starting with a Python file object f,
# # first do f.flush(), and
2021-04-26 20:07:00 +02:00
# # then do os.fsync(f.fileno()), to ensure that all internal buffers associated with f are written to disk.
# global os
#
2021-04-26 20:07:00 +02:00
# file_handle.flush()
# os.fsync(file_handle.fileno())
#
2021-04-26 20:07:00 +02:00
# file_handle.close()
#
2021-04-26 20:07:00 +02:00
# #--------------------------------------------
#
2021-04-26 20:07:00 +02:00
# def cleanup( f_names_list ):
# global os
# for i in range(len( f_names_list )):
# if os.path.isfile( f_names_list[i]):
# os.remove( f_names_list[i] )
# if os.path.isfile( f_names_list[i]):
# print('ERROR: can not remove file ' + f_names_list[i])
#
2021-04-26 20:07:00 +02:00
# #-------------------------------------------
#
#
2021-04-26 20:07:00 +02:00
# def svc_get_fb_log( engine, f_fb_log ):
#
2021-04-26 20:07:00 +02:00
# import subprocess
#
2021-04-26 20:07:00 +02:00
# if engine.startswith('2.5'):
# get_firebird_log_key='action_get_ib_log'
# else:
# get_firebird_log_key='action_get_fb_log'
#
2021-04-26 20:07:00 +02:00
# subprocess.call([ context['fbsvcmgr_path'],
# "localhost:service_mgr",
# get_firebird_log_key
# ],
# stdout=f_fb_log,
2021-04-26 20:07:00 +02:00
# stderr=subprocess.STDOUT
# )
#
2021-04-26 20:07:00 +02:00
# return
#
2021-04-26 20:07:00 +02:00
# #--------------------------------------------
#
2021-04-26 20:07:00 +02:00
# # http://stackoverflow.com/questions/319279/how-to-validate-ip-address-in-python
# def is_valid_ipv4(address):
# import socket
# try:
# socket.inet_pton(socket.AF_INET, address)
# except AttributeError: # no inet_pton here, sorry
# try:
# socket.inet_aton(address)
# except socket.error:
# return False
# return address.count('.') == 3
# except socket.error: # not a valid address
# return False
#
2021-04-26 20:07:00 +02:00
# return True
#
2021-04-26 20:07:00 +02:00
# #--------------------------------------------
#
2021-04-26 20:07:00 +02:00
# def is_valid_ipv6(address):
# import socket
# try:
# socket.inet_pton(socket.AF_INET6, address)
# except socket.error: # not a valid address
# return False
# return True
#
2021-04-26 20:07:00 +02:00
# #--------------------------------------------
#
2021-04-26 20:07:00 +02:00
# f_fblog_before=open(os.path.join(context['temp_directory'],'tmp_2493_fblog_before.txt'), 'w')
#
2021-04-26 20:07:00 +02:00
# svc_get_fb_log( engine, f_fblog_before )
#
2021-04-26 20:07:00 +02:00
# f_fblog_before.close()
#
2021-04-26 20:07:00 +02:00
# isql_txt=''' insert into log(ip) values( rdb$get_context('SYSTEM','CLIENT_ADDRESS') );
# commit;
# select count(i) from (select gen_id(g,1) i from rdb$types a,rdb$types b,rdb$types c,rdb$types d);
# '''
#
2021-04-26 20:07:00 +02:00
# f_sql_txt=open( os.path.join(context['temp_directory'],'tmp_2493_isql.sql'), 'w')
# f_sql_txt.write(isql_txt)
# flush_and_close( f_sql_txt )
#
2021-04-26 20:07:00 +02:00
# f_sql_log=open(os.path.join(context['temp_directory'],'tmp_2493_isql.log'), 'w' )
# f_sql_err=open(os.path.join(context['temp_directory'],'tmp_2493_isql.err'), 'w' )
#
2021-04-26 20:07:00 +02:00
# p_isql=Popen( [ context['isql_path'], dsn, "-i", f_sql_txt.name ], stdout=f_sql_log, stderr=f_sql_err
# )
# time.sleep(3)
#
2021-04-26 20:07:00 +02:00
# p_isql.terminate()
#
2021-04-26 20:07:00 +02:00
# flush_and_close( f_sql_log )
# flush_and_close( f_sql_err )
#
2021-04-26 20:07:00 +02:00
# f_sql_txt=open(os.path.join(context['temp_directory'],'tmp_2493_isql.sql'), 'w')
# f_sql_txt.write("set heading off; select iif(gen_id(g,0) = 0, 'Trouble with subprocess: job was not started.', ip) as msg from log; quit;")
# flush_and_close( f_sql_txt )
#
2021-04-26 20:07:00 +02:00
# mon_ip=subprocess.check_output( [ context['isql_path'], dsn, '-i', f_sql_txt.name ]).split()[0]
#
2021-04-26 20:07:00 +02:00
# f_fblog_after=open(os.path.join(context['temp_directory'],'tmp_2493_fblog_after.txt'), 'w')
#
2021-04-26 20:07:00 +02:00
# svc_get_fb_log( engine, f_fblog_after )
#
2021-04-26 20:07:00 +02:00
# flush_and_close( f_fblog_after )
#
2021-04-26 20:07:00 +02:00
# oldfb=open(f_fblog_before.name, 'r')
# newfb=open(f_fblog_after.name, 'r')
#
2021-04-26 20:07:00 +02:00
# difftext = ''.join(difflib.unified_diff(
# oldfb.readlines(),
2021-04-26 20:07:00 +02:00
# newfb.readlines()
# ))
# oldfb.close()
# newfb.close()
#
2021-04-26 20:07:00 +02:00
# f_diff_txt=open( os.path.join(context['temp_directory'],'tmp_2493_diff.txt'), 'w')
# f_diff_txt.write(difftext)
# flush_and_close( f_diff_txt )
#
2021-04-26 20:07:00 +02:00
# inet_msg_words = []
# logged_err=0
# with open( f_diff_txt.name,'r') as f:
# for line in f:
# if line.startswith('+') and 'INET/INET_ERROR' in line.upper():
# # DO NOT include ':' to the list of delimiters! It is involved in IPv6 address:
# inet_msg_words = line.replace(',',' ').replace('/',' ').replace('=',' ').split()
# break
#
2021-04-26 20:07:00 +02:00
# # Tokens, numerated from zero (NB: leftmost is "PLUS" sign and has index = 0)
# # ---------------------------------------------------------------------------
# # + INET inet_error read errno 10054 client host prog1 address 127.0.0.1 4417 user john ------- for IPv4
# # 0 1 2 3 4 5 6 7 8 9 10 11 12 13
# # + INET inet_error read errno 10054 client host prog2 address x::y:z:u:v 56831 user mick ------- for IPv6
#
2021-04-26 20:07:00 +02:00
# # + INET/inet_error: read errno = 10054, client host = csprog, address = fe80::fcf1:e33c:e924:969d%16/56883, user = zotov
# # 0 1 2 3 4 5 6 7 8 9 10 11 12 --> len() = 13
#
2021-04-26 20:07:00 +02:00
# n = len(inet_msg_words)
#
2021-04-26 20:07:00 +02:00
# parsing_problem_msg = 'Problem with parsing content of firebird.log'
# if len(inet_msg_words) == 0:
# print('%s: message with "inet_error" not found.' % parsing_problem_msg)
# elif len(inet_msg_words) < 4:
# print('%s: message with "inet_error" contains less than 4 tokens.' % parsing_problem_msg)
# else:
#
2021-04-26 20:07:00 +02:00
# #print('Fixed data: '+inet_msg_words[4]+' '+inet_msg_words[5]+' '+inet_msg_words[6]+' '+inet_msg_words[7])
#
2021-04-26 20:07:00 +02:00
# # http://stackoverflow.com/questions/4271740/how-can-i-use-python-to-get-the-system-hostname
#
2021-04-26 20:07:00 +02:00
# # commented 17.02.2017 due to 2.5.9 (no info about remote host there):
# #if inet_msg_words[8].upper()==socket.gethostname().upper():
# # print('Remote host: valid, passed socket.gethostname()')
# #else:
# # print('Invalid host=|'+inet_msg_words[8]+'|')
#
2021-04-26 20:07:00 +02:00
# # does not work on Python 3.4! >>> if is_valid_ipv4(inet_msg_words[10]) or is_valid_ipv6(inet_msg_words[10]):
# if inet_msg_words[n-4] + '/' + inet_msg_words[n-3] == mon_ip:
# print("String IP/port: valid, equal to 'CLIENT_ADDRESS'")
# else:
# print('Invalid IP/port=|'+inet_msg_words[n-4]+'/'+inet_msg_words[n-3]+'| - differ from mon_ip=|'+mon_ip+'|')
#
2021-04-26 20:07:00 +02:00
# if inet_msg_words[n-3].isdigit():
# print('Port value: valid, positive integer.')
# else:
# print('Invalid port=|'+inet_msg_words[n-3]+'|')
#
2021-04-26 20:07:00 +02:00
# if inet_msg_words[n-1].upper().split('.')[0] == getpass.getuser().upper():
# # 2.5.9: got 'ZOTOV.-1.-1' ==> must be kust of one word: 'ZOTOV'
# print('OS user: valid, passed getpass.getuser()')
# else:
# print('Invalid OS user=|'+inet_msg_words[n-1]+'|')
#
#
2021-04-26 20:07:00 +02:00
# # Cleanup.
# ##########
# time.sleep(1)
# cleanup( [i.name for i in (f_sql_txt,f_sql_log,f_sql_err,f_fblog_before,f_fblog_after,f_diff_txt) ] )
#
#
2021-04-26 20:07:00 +02:00
#---