mirror of
https://github.com/FirebirdSQL/firebird-qa.git
synced 2025-01-22 13:33:07 +01:00
Plugin v0.9.1
This commit is contained in:
parent
75419c92a2
commit
ec75b37214
@ -41,6 +41,7 @@ from typing import Dict, List, Tuple
|
||||
import os
|
||||
from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
|
||||
from pathlib import Path
|
||||
from operator import attrgetter
|
||||
from packaging.version import Version, parse
|
||||
|
||||
PROG_NAME = 'fbt-convert'
|
||||
@ -69,6 +70,12 @@ tests = []
|
||||
|
||||
slow_tests = ['bugs.core_1544', 'bugs.core_3058']
|
||||
|
||||
def clean_last(txt: str) -> str:
|
||||
if not txt:
|
||||
return txt
|
||||
l = txt.splitlines()
|
||||
l[-1] = l[-1].strip()
|
||||
return '\n'.join(l)
|
||||
|
||||
class TestVersion:
|
||||
def __init__(self, id, platform, firebird_version, test_type,
|
||||
@ -82,10 +89,10 @@ class TestVersion:
|
||||
self.platform: str = platform
|
||||
self.firebird_version: Version = parse(firebird_version)
|
||||
self.test_type: str = test_type
|
||||
self.test_script: str = test_script
|
||||
self.test_script: str = clean_last(test_script)
|
||||
self.database: str = database
|
||||
self.expected_stdout: str = '' if expected_stdout.strip() == '' else expected_stdout
|
||||
self.expected_stderr: str = '' if expected_stderr.strip() == '' else expected_stderr
|
||||
self.expected_stdout: str = clean_last('' if expected_stdout.strip() == '' else expected_stdout)
|
||||
self.expected_stderr: str = clean_last('' if expected_stderr.strip() == '' else expected_stderr)
|
||||
self.database_name: str = database_name
|
||||
self.backup_file: str = backup_file
|
||||
self.user_name: str = user_name
|
||||
@ -98,6 +105,7 @@ class TestVersion:
|
||||
self.resources: List[str] = None if resources is None else list(resources)
|
||||
self.substitutions: List[str] = substitutions if substitutions is not None else []
|
||||
self.qmid: str = qmid
|
||||
# Clean
|
||||
def escape(self, subs: List[Tuple[str, str]]) -> List[Tuple[str, str]]:
|
||||
return [tuple([a.replace('\\', '\\\\'), b.replace('\\', '\\\\')]) for a, b in subs]
|
||||
|
||||
@ -117,6 +125,7 @@ class Test:
|
||||
if versions:
|
||||
for i in versions:
|
||||
self.versions.append(TestVersion(id, **i))
|
||||
self.versions.sort(key=attrgetter('firebird_version'))
|
||||
def show(self):
|
||||
for attr in (a for a in dir(self) if not a.startswith('_')):
|
||||
if attr not in ('show'):
|
||||
@ -168,6 +177,7 @@ def load_tests(path: Path, verbose: bool=False):
|
||||
|
||||
def clean_tests():
|
||||
v30: Version = parse('3.0')
|
||||
v40: Version = parse('4.0')
|
||||
for t in tests:
|
||||
new_versions = []
|
||||
last: Version = parse('0.1')
|
||||
@ -179,15 +189,15 @@ def clean_tests():
|
||||
if mv > v.firebird_version:
|
||||
v.firebird_version = mv
|
||||
#
|
||||
if last < v.firebird_version:
|
||||
if (last < v.firebird_version) and (v.firebird_version < v30):
|
||||
last = v.firebird_version
|
||||
if v.firebird_version >= v30:
|
||||
has_30 = True
|
||||
has_30 = has_30 or v.firebird_version < v40
|
||||
new_versions.append(v)
|
||||
if not has_30:
|
||||
for v in t.versions:
|
||||
if v.firebird_version >= last:
|
||||
new_versions.append(v)
|
||||
if v.firebird_version == last:
|
||||
new_versions.insert(0, v)
|
||||
t.versions[:] = new_versions
|
||||
|
||||
def list_tests(root_path: Path, verbose: bool=False):
|
||||
@ -233,7 +243,7 @@ def write_tests(root_path: Path, verbose: bool=False):
|
||||
# qmid: {t.qmid}
|
||||
|
||||
import pytest
|
||||
from firebird.qa import db_factory, isql_act, Action
|
||||
from firebird.qa import db_factory, {'isql_act' if t.versions[0].test_type == TYPE_ISQL else 'python_act'}, Action
|
||||
|
||||
"""
|
||||
# verbose output
|
||||
@ -292,25 +302,34 @@ from firebird.qa import db_factory, isql_act, Action
|
||||
content += f' act_{seq}.expected_stderr = expected_stderr_{seq}\n'
|
||||
content += f' act_{seq}.execute()\n'
|
||||
if v.expected_stderr:
|
||||
content += f' assert act_{seq}.clean_expected_stderr == act_{seq}.clean_stderr\n'
|
||||
content += f' assert act_{seq}.clean_stderr == act_{seq}.clean_expected_stderr\n'
|
||||
if v.expected_stdout:
|
||||
content += f' assert act_{seq}.clean_expected_stdout == act_{seq}.clean_stdout\n'
|
||||
if v.expected_stderr:
|
||||
content += '\n'
|
||||
content += f' assert act_{seq}.clean_stdout == act_{seq}.clean_expected_stdout\n'
|
||||
content += '\n'
|
||||
elif v.test_type == TYPE_PYTHON:
|
||||
#
|
||||
content += f'''# test_script_{seq}\n#---\n# {multiline_comment(escape(v.test_script), 2)}\n#---\n'''
|
||||
content += f"#act_{seq} = python_act('db_{seq}', test_script_{seq}, substitutions=substitutions_{seq})\n\n"
|
||||
if v.expected_stdout:
|
||||
sep = "'''" if v.expected_stdout.startswith('"') or v.expected_stdout.endswith('"') else '"""'
|
||||
content += f'expected_stdout_{seq} = {sep}{escape(v.expected_stdout)}{sep}\n'
|
||||
content += f"act_{seq} = python_act('db_{seq}', substitutions=substitutions_{seq})\n\n"
|
||||
if v.expected_stderr:
|
||||
sep = "'''" if v.expected_stderr.startswith('"') or v.expected_stderr.endswith('"') else '"""'
|
||||
content += f'expected_stderr_{seq} = {sep}{escape(v.expected_stderr)}{sep}\n'
|
||||
content += f"""\n@pytest.mark.version('>={str(v.firebird_version)}')\n"""
|
||||
if v.expected_stdout:
|
||||
if v.expected_stderr:
|
||||
content += '\n'
|
||||
sep = "'''" if v.expected_stdout.startswith('"') or v.expected_stdout.endswith('"') else '"""'
|
||||
content += f'expected_stdout_{seq} = {sep}{escape(v.expected_stdout)}{sep}\n'
|
||||
# Version specification
|
||||
if seq < len(t.versions):
|
||||
ver_spec = f'>={str(v.firebird_version)},<{str(t.versions[seq].firebird_version)}'
|
||||
else:
|
||||
ver_spec = f'>={str(v.firebird_version)}'
|
||||
content += f"""\n@pytest.mark.version('{ver_spec}')\n"""
|
||||
if v.platform != 'All':
|
||||
content += f"""@pytest.mark.platform({", ".join([f"'{i}'" for i in v.platform.split(':')])})\n"""
|
||||
content += "@pytest.mark.xfail\n"
|
||||
content += f"""def test_{seq}(db_{seq}):\n pytest.fail("Test not IMPLEMENTED")\n\n"""
|
||||
#content += "@pytest.mark.xfail\n"
|
||||
content += f"""def test_{seq}(act_{seq}: Action):\n pytest.fail("Test not IMPLEMENTED")\n\n"""
|
||||
content += '\n'
|
||||
|
||||
#
|
||||
|
@ -47,7 +47,7 @@ import pytest
|
||||
from _pytest.fixtures import FixtureRequest
|
||||
from subprocess import run, CompletedProcess, PIPE, STDOUT
|
||||
from pathlib import Path
|
||||
#from configparser import ConfigParser, ExtendedInterpolation
|
||||
from configparser import ConfigParser, ExtendedInterpolation
|
||||
from packaging.specifiers import SpecifierSet
|
||||
from packaging.version import parse
|
||||
import time
|
||||
@ -55,7 +55,7 @@ from threading import Thread, Barrier
|
||||
from firebird.driver import connect, connect_server, create_database, driver_config, \
|
||||
NetProtocol, Server, CHARSET_MAP, Connection, Cursor, \
|
||||
DESCRIPTION_NAME, DESCRIPTION_DISPLAY_SIZE, DatabaseConfig, DBKeyScope, DbInfoCode, \
|
||||
DbWriteMode, DatabaseError
|
||||
DbWriteMode, get_api
|
||||
from firebird.driver.core import _connect_helper
|
||||
|
||||
_vars_ = {'server': None,
|
||||
@ -90,6 +90,7 @@ def pytest_report_header(config):
|
||||
f" home: {_vars_['home-dir']}",
|
||||
f" bin: {_vars_['bin-dir']}",
|
||||
f" security db: {_vars_['security-db']}",
|
||||
f" client library: {_vars_['fbclient']}",
|
||||
f" run slow tests: {_vars_['runslow']}",
|
||||
f" save test output: {_vars_['save-output']}",
|
||||
]
|
||||
@ -142,7 +143,18 @@ def pytest_configure(config):
|
||||
db_conf = driver_config.get_database('employee')
|
||||
db_conf.server.value = _vars_['server']
|
||||
db_conf.database.value = 'employee.fdb'
|
||||
#
|
||||
# Handle server-specific "fb_client_library" configuration option
|
||||
_vars_['fbclient'] = 'UNKNOWN'
|
||||
cfg = ConfigParser(interpolation=ExtendedInterpolation())
|
||||
cfg.read(str(config_path))
|
||||
if cfg.has_option(_vars_['server'], 'fb_client_library'):
|
||||
fbclient = Path(cfg.get(_vars_['server'], 'fb_client_library'))
|
||||
if not fbclient.is_file():
|
||||
pytest.exit(f"Client library '{fbclient}' not found!")
|
||||
driver_config.fb_client_library.value = str(fbclient)
|
||||
cfg.clear()
|
||||
# THIS should load the driver API, do not connect db or server earlier!
|
||||
_vars_['fbclient'] = get_api().client_library_name
|
||||
with connect_server(_vars_['server'], user='SYSDBA',
|
||||
password=_vars_['password']) as srv:
|
||||
_vars_['version'] = parse(srv.info.version.replace('-dev', ''))
|
||||
@ -187,16 +199,15 @@ def pytest_collection_modifyitems(session, config, items):
|
||||
items[:] = selected
|
||||
config.hook.pytest_deselected(items=deselected)
|
||||
|
||||
#@pytest.fixture(autouse=True)
|
||||
#def firebird_server():
|
||||
#try:
|
||||
#with connect_server(_vars_['server']) as srv:
|
||||
#yield srv
|
||||
#except DatabaseError as e:
|
||||
#print('ERROR WHILE DETACH FROM SERVER:', e)
|
||||
## Shield from crashing server
|
||||
#if 'Error reading data from the connection' not in str(e):
|
||||
#raise
|
||||
#@pytest.hookimpl(hookwrapper=True)
|
||||
#def pytest_runtest_makereport(item, call):
|
||||
#outcome = yield
|
||||
#report = outcome.get_result()
|
||||
|
||||
#test_fn = item.obj
|
||||
#docstring = getattr(test_fn, '__doc__')
|
||||
#if docstring:
|
||||
#report.nodeid = docstring
|
||||
|
||||
def substitute_macros(text: str, macros: Dict[str, str]):
|
||||
f_text = text
|
||||
@ -208,7 +219,8 @@ def substitute_macros(text: str, macros: Dict[str, str]):
|
||||
class Database:
|
||||
""
|
||||
def __init__(self, path: Path, filename: str='test.fdb',
|
||||
user: str=None, password: str=None, charset: str=None):
|
||||
user: str=None, password: str=None, charset: str=None, debug: str=''):
|
||||
self._debug: str = debug
|
||||
self.db_path: Path = path / filename
|
||||
self.dsn: str = None
|
||||
self.charset: str = 'NONE' if charset is None else charset.upper()
|
||||
@ -298,19 +310,30 @@ class Database:
|
||||
with connect_server(_vars_['server']) as srv:
|
||||
srv.database.no_linger(database=self.db_path)
|
||||
self._make_config()
|
||||
db = connect('pytest')
|
||||
with connect('pytest') as db:
|
||||
db._att._name = self._debug
|
||||
try:
|
||||
db.execute_immediate('delete from mon$attachments where mon$attachment_id != current_connection')
|
||||
db.commit()
|
||||
except:
|
||||
pass
|
||||
#print(f"Removing db: {self.db_path}")
|
||||
try:
|
||||
db.drop_database()
|
||||
except:
|
||||
pass
|
||||
if self.db_path.is_file():
|
||||
self.db_path.unlink(missing_ok=True)
|
||||
def connect(self, *, user: str=None, password: str=None, role: str=None, no_gc: bool=None,
|
||||
no_db_triggers: bool=None, dbkey_scope: DBKeyScope=None,
|
||||
session_time_zone: str=None, charset: str=None, sql_dialect: int=None,
|
||||
auth_plugin_list: str=None) -> Connection:
|
||||
self._make_config(user=user, password=password, charset=charset, sql_dialect=sql_dialect)
|
||||
return connect('pytest', role=role, no_gc=no_gc, no_db_triggers=no_db_triggers,
|
||||
result = connect('pytest', role=role, no_gc=no_gc, no_db_triggers=no_db_triggers,
|
||||
dbkey_scope=dbkey_scope, session_time_zone=session_time_zone,
|
||||
auth_plugin_list=auth_plugin_list)
|
||||
result._att._name = self._debug
|
||||
return result
|
||||
def set_async_write(self) -> None:
|
||||
with connect_server(_vars_['server']) as srv:
|
||||
srv.database.set_write_mode(database=self.db_path, mode=DbWriteMode.ASYNC)
|
||||
@ -325,7 +348,7 @@ def db_factory(*, filename: str='test.fdb', init: str=None, from_backup: str=Non
|
||||
|
||||
@pytest.fixture
|
||||
def database_fixture(request: FixtureRequest, db_path) -> Database:
|
||||
db = Database(db_path, filename, user, password, charset)
|
||||
db = Database(db_path, filename, user, password, charset, debug=str(request.module))
|
||||
if not do_not_create:
|
||||
if from_backup is None and copy_of is None:
|
||||
db.create(page_size, sql_dialect)
|
||||
|
@ -5,7 +5,7 @@ all-files=True
|
||||
|
||||
[metadata]
|
||||
name = firebird-qa
|
||||
version = 0.9.0
|
||||
version = 0.9.1
|
||||
description = pytest plugin for Firebird QA
|
||||
long_description = file: README.rst
|
||||
long_description_content_type = text/x-rst; charset=UTF-8
|
||||
@ -38,7 +38,7 @@ zip_safe = True
|
||||
python_requires = >=3.8, <4
|
||||
install_requires =
|
||||
firebird-base>=1.3.0
|
||||
firebird-driver>=1.4.0
|
||||
firebird-driver>=1.4.1
|
||||
pytest>=6.2.5
|
||||
packages = find_namespace:
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user