mirror of
https://github.com/FirebirdSQL/firebird-qa.git
synced 2025-01-22 13:33:07 +01:00
Changes in plugin + some tests fixed
This commit is contained in:
parent
98f16f425a
commit
59fcb66ce0
@ -51,7 +51,7 @@ from configparser import ConfigParser, ExtendedInterpolation
|
||||
from packaging.specifiers import SpecifierSet
|
||||
from packaging.version import Version, parse
|
||||
from firebird.driver import connect, connect_server, create_database, driver_config, \
|
||||
NetProtocol, PageSize, Server
|
||||
NetProtocol, PageSize, Server, CHARSET_MAP
|
||||
|
||||
_vars_ = {'server': None,
|
||||
'bin-dir': None,
|
||||
@ -144,22 +144,29 @@ def pytest_configure(config):
|
||||
set_tool(tool)
|
||||
|
||||
|
||||
def pytest_collection_modifyitems(config, items):
|
||||
def pytest_collection_modifyitems(session, config, items):
|
||||
skip_slow = pytest.mark.skip(reason="need --runslow option to run")
|
||||
skip_platform = pytest.mark.skip(reason=f"test not designed for {_platform}")
|
||||
skip_version = pytest.mark.skip(reason=f"test not designed for {_vars_['version']}")
|
||||
# Apply skip markers
|
||||
for item in items:
|
||||
if 'slow' in item.keywords and not _vars_['runslow']:
|
||||
item.add_marker(skip_slow)
|
||||
platforms = [mark.args for mark in item.iter_markers(name="platform")]
|
||||
for items in platforms:
|
||||
if _platform not in items:
|
||||
for platforms in [mark.args for mark in item.iter_markers(name="platform")]:
|
||||
if _platform not in platforms:
|
||||
item.add_marker(skip_platform)
|
||||
# Deselect tests not applicable to tested engine version
|
||||
selected = []
|
||||
deselected = []
|
||||
for item in items:
|
||||
versions = [mark.args for mark in item.iter_markers(name="version")]
|
||||
if versions:
|
||||
spec = SpecifierSet(','.join(list(versions[0])))
|
||||
if _vars_['version'] not in spec:
|
||||
item.add_marker(skip_version)
|
||||
if _vars_['version'] in spec:
|
||||
selected.append(item)
|
||||
else:
|
||||
deselected.append(item)
|
||||
items[:] = selected
|
||||
config.hook.pytest_deselected(items=deselected)
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def firebird_server():
|
||||
@ -183,8 +190,8 @@ class Database:
|
||||
self.dsn = f"{_vars_['host']}:{str(self.db_path)}"
|
||||
else:
|
||||
self.dsn = str(self.db_path)
|
||||
self.subs = {'temp_directory': str(path), 'database_location': str(path),
|
||||
'DATABASE_PATH': str(path), 'DSN': self.dsn,
|
||||
self.subs = {'temp_directory': str(path / 'x')[:-1], 'database_location': str(path / 'x')[:-1],
|
||||
'DATABASE_PATH': str(path / 'x')[:-1], 'DSN': self.dsn,
|
||||
'files_location': str(_vars_['root'] / 'files'),
|
||||
'backup_location': str(_vars_['root'] / 'backups'),
|
||||
'suite_database_location': str(_vars_['root'] / 'databases'),
|
||||
@ -210,7 +217,7 @@ class Database:
|
||||
def create(self, page_size: int=None, sql_dialect: int=None, charset: str=None) -> None:
|
||||
#__tracebackhide__ = True
|
||||
self._make_config(page_size, sql_dialect, charset)
|
||||
#print(f"Creating db: {self.db_path} [{page_size=}, {sql_dialect=}, {charset=}, user={self.user}, password={self.password}]")
|
||||
print(f"Creating db: {self.db_path} [{page_size=}, {sql_dialect=}, {charset=}, user={self.user}, password={self.password}]")
|
||||
db = create_database('pytest')
|
||||
db.close()
|
||||
def restore(self, backup: str) -> None:
|
||||
@ -227,7 +234,7 @@ class Database:
|
||||
print(result.stdout)
|
||||
print(f"-- stderr {'-' * 20}")
|
||||
print(result.stderr)
|
||||
raise CalledProcessError(result.returncode, result.args, result.stdout, result.stderr)
|
||||
raise Exception("Database restore failed")
|
||||
# Fix permissions
|
||||
#if platform.system != 'Windows':
|
||||
#os.chmod(self.db_path, 16895)
|
||||
@ -252,21 +259,25 @@ class Database:
|
||||
print(result.stdout)
|
||||
print(f"-- stderr {'-' * 20}")
|
||||
print(result.stderr)
|
||||
raise CalledProcessError(result.returncode, result.args, result.stdout, result.stderr)
|
||||
raise Exception("Database init script execution failed")
|
||||
return result
|
||||
def execute(self, script: str, *, raise_on_fail: bool) -> CompletedProcess:
|
||||
def execute(self, script: str, *, raise_on_fail: bool, charset: str='utf8') -> CompletedProcess:
|
||||
__tracebackhide__ = True
|
||||
#print("Running test script")
|
||||
result = run([_vars_['isql'], '-ch', 'utf8', '-user', self.user,
|
||||
if charset:
|
||||
charset = charset.upper()
|
||||
else:
|
||||
charset = 'NONE'
|
||||
result = run([_vars_['isql'], '-ch', charset, '-user', self.user,
|
||||
'-password', self.password, str(self.dsn)],
|
||||
input=substitute_macros(script, self.subs),
|
||||
encoding='utf8', capture_output=True)
|
||||
encoding=CHARSET_MAP[charset], capture_output=True)
|
||||
if result.returncode and raise_on_fail:
|
||||
print(f"-- stdout {'-' * 20}")
|
||||
print(result.stdout)
|
||||
print(f"-- stderr {'-' * 20}")
|
||||
print(result.stderr)
|
||||
raise CalledProcessError(result.returncode, result.args, result.stdout, result.stderr)
|
||||
raise Exception("ISQL script execution failed")
|
||||
return result
|
||||
def drop(self) -> None:
|
||||
self._make_config()
|
||||
@ -332,9 +343,11 @@ def db_factory(*, filename: str='test.fdb', init: str=None, from_backup: str=Non
|
||||
return database_fixture
|
||||
|
||||
class Action:
|
||||
def __init__(self, db: Database, script: str, substitutions: List[str]):
|
||||
def __init__(self, db: Database, script: str, substitutions: List[str], outfile: Path,
|
||||
charset: str):
|
||||
self.db: Database = db
|
||||
self.script: str = script
|
||||
self.charset: str = charset
|
||||
self.return_code: int = 0
|
||||
self.stdout: str = ''
|
||||
self._clean_stdout: str = None
|
||||
@ -345,6 +358,7 @@ class Action:
|
||||
self.expected_stderr: str = ''
|
||||
self._clean_expected_stderr: str = None
|
||||
self.substitutions: List[str] = [x for x in substitutions]
|
||||
self.outfile: Path = outfile
|
||||
def make_diff(self, left: str, right: str) -> str:
|
||||
return '\n'.join(difflib.ndiff(left.splitlines(), right.splitlines()))
|
||||
def space_strip(self, value: str) -> str:
|
||||
@ -369,11 +383,23 @@ class Action:
|
||||
return value
|
||||
def execute(self) -> None:
|
||||
__tracebackhide__ = True
|
||||
out_file: Path = self.outfile.with_suffix('.out')
|
||||
err_file: Path = self.outfile.with_suffix('.err')
|
||||
if out_file.is_file():
|
||||
out_file.unlink()
|
||||
if err_file.is_file():
|
||||
err_file.unlink()
|
||||
result: CompletedProcess = self.db.execute(self.script,
|
||||
raise_on_fail=not bool(self.expected_stderr))
|
||||
raise_on_fail=not bool(self.expected_stderr),
|
||||
charset=self.charset)
|
||||
self.return_code: int = result.returncode
|
||||
self.stdout: str = result.stdout
|
||||
self.stderr: str = result.stderr
|
||||
# Store output
|
||||
if self.stdout:
|
||||
out_file.write_text(self.stdout)
|
||||
if self.stderr:
|
||||
err_file.write_text(self.stderr)
|
||||
@property
|
||||
def clean_stdout(self) -> str:
|
||||
if self._clean_stdout is None:
|
||||
@ -395,12 +421,18 @@ class Action:
|
||||
self._clean_expected_stderr = self.string_strip(self.expected_stderr, self.substitutions)
|
||||
return self._clean_expected_stderr
|
||||
|
||||
def isql_act(db_fixture_name: str, script: str, *, substitutions: List[str]=None):
|
||||
def isql_act(db_fixture_name: str, script: str, *, substitutions: List[str]=None,
|
||||
charset: str='utf8'):
|
||||
|
||||
@pytest.fixture
|
||||
def isql_act_fixture(request: FixtureRequest) -> Action:
|
||||
db: Database = request.getfixturevalue(db_fixture_name)
|
||||
result: Action = Action(db, script, substitutions)
|
||||
f: Path = Path.cwd() / 'out' / request.module.__name__.replace('.', '/')
|
||||
if not f.parent.exists():
|
||||
f.parent.mkdir(parents=True)
|
||||
f = f.with_name(f'{f.stem}-{request.function.__name__}.out')
|
||||
#f.write_text('stdout')
|
||||
result: Action = Action(db, script, substitutions, f, charset)
|
||||
return result
|
||||
|
||||
return isql_act_fixture
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -118,13 +118,14 @@ test_script_1 = """
|
||||
act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1)
|
||||
|
||||
expected_stdout_1 = """
|
||||
/* Grant permissions for this database */
|
||||
GRANT SELECT ON t t TO ROLE FOR
|
||||
GRANT FOR CVC TO CVC
|
||||
/* Grant permissions for this database */
|
||||
GRANT SELECT ON t t TO ROLE FOR
|
||||
GRANT FOR CVC TO CVC
|
||||
GRANT CREATE DATABASE TO USER TMP$C4648
|
||||
|
||||
WHO_AM_I CVC
|
||||
I_M_PLAYING_ROLE FOR CVC
|
||||
"""
|
||||
WHO_AM_I CVC
|
||||
I_M_PLAYING_ROLE FOR CVC
|
||||
"""
|
||||
expected_stderr_1 = """
|
||||
Statement failed, SQLSTATE = 42000
|
||||
Execute statement error at isc_dsql_prepare :
|
||||
|
@ -47,22 +47,26 @@ select * from X_VW where description like 'xyz%' ;
|
||||
|
||||
act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1)
|
||||
|
||||
expected_stdout_1 = """ ID DESCRIPTION
|
||||
===================== =========================================================================
|
||||
expected_stdout_1 = """
|
||||
ID DESCRIPTION
|
||||
===================== ======================================================================
|
||||
1 xyz (1)
|
||||
2 xyzxyz (2)
|
||||
3 xyz012 (3)
|
||||
|
||||
ID DESCRIPTION
|
||||
===================== =========================================================================
|
||||
1 xyz (1)
|
||||
|
||||
ID DESCRIPTION
|
||||
===================== =========================================================================
|
||||
===================== ======================================================================
|
||||
1 xyz (1)
|
||||
|
||||
|
||||
ID DESCRIPTION
|
||||
===================== =========================================================================
|
||||
===================== ======================================================================
|
||||
1 xyz (1)
|
||||
|
||||
|
||||
ID DESCRIPTION
|
||||
===================== ======================================================================
|
||||
1 xyz (1)
|
||||
2 xyzxyz (2)
|
||||
3 xyz012 (3)
|
||||
|
@ -38,7 +38,7 @@ test_script_1 = """
|
||||
grant update (col2) on tab2 to role1;
|
||||
commit;
|
||||
|
||||
connect 'localhost:$(DATABASE_LOCATION)bugs.core_1083.fdb' user 'TMP$C1083' password 'QweRtyUioP';
|
||||
connect 'localhost:$(DATABASE_LOCATION)test.fdb' user 'TMP$C1083' password 'QweRtyUioP';
|
||||
--set bail on;
|
||||
set echo on;
|
||||
grant update(col1) on tab1 to role1;
|
||||
@ -47,7 +47,7 @@ test_script_1 = """
|
||||
set echo off;
|
||||
commit;
|
||||
|
||||
connect 'localhost:$(DATABASE_LOCATION)bugs.core_1083.fdb' user 'SYSDBA' password 'masterkey';
|
||||
connect 'localhost:$(DATABASE_LOCATION)test.fdb' user 'SYSDBA' password 'masterkey';
|
||||
set echo on;
|
||||
drop user tmp$c1083;
|
||||
set echo off;
|
||||
|
@ -59,19 +59,28 @@ test_script_1 = """
|
||||
act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1)
|
||||
|
||||
expected_stdout_1 = """
|
||||
F1 0123456789
|
||||
F2 abcdefghij
|
||||
CF 0123456789 - abcdefghij
|
||||
FLD_NAME CF
|
||||
FLD_EXPR (f1 || ' - ' || f2)
|
||||
FLD_LENGTH 23
|
||||
F1 0123456789
|
||||
F2 abcdefghij
|
||||
CF 0123456789 - abcdefghij - more
|
||||
FLD_NAME CF
|
||||
FLD_EXPR (f1 || ' - ' || f2 || ' - more')
|
||||
FLD_LENGTH 30
|
||||
"""
|
||||
F1 0123456789
|
||||
F2 abcdefghij
|
||||
CF 0123456789 - abcdefghij
|
||||
|
||||
|
||||
|
||||
FLD_NAME CF
|
||||
FLD_EXPR (f1 || ' - ' || f2)
|
||||
FLD_LENGTH 92
|
||||
|
||||
|
||||
|
||||
F1 0123456789
|
||||
F2 abcdefghij
|
||||
CF 0123456789 - abcdefghij - more
|
||||
|
||||
|
||||
|
||||
FLD_NAME CF
|
||||
FLD_EXPR (f1 || ' - ' || f2 || ' - more')
|
||||
FLD_LENGTH 120
|
||||
"""
|
||||
|
||||
@pytest.mark.version('>=2.5.0')
|
||||
def test_1(act_1: Action):
|
||||
|
@ -25,10 +25,9 @@ test_script_1 = """SELECT DATEDIFF(DAY, CAST('18.10.2007' AS TIMESTAMP), CAST('2
|
||||
act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1)
|
||||
|
||||
expected_stdout_1 = """
|
||||
DATEDIFF
|
||||
=======================
|
||||
5.000000000000000
|
||||
|
||||
DATEDIFF
|
||||
=====================
|
||||
5
|
||||
"""
|
||||
|
||||
@pytest.mark.version('>=2.1')
|
||||
|
@ -32,13 +32,12 @@ test_script_1 = """SELECT ABS(MYNUM) FROM TEST;"""
|
||||
act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1)
|
||||
|
||||
expected_stdout_1 = """
|
||||
ABS
|
||||
=======================
|
||||
1.000000000000000
|
||||
1.000000000000000
|
||||
2147483647.000000
|
||||
2147483648.000000
|
||||
|
||||
ABS
|
||||
=====================
|
||||
1
|
||||
1
|
||||
2147483647
|
||||
2147483648
|
||||
"""
|
||||
|
||||
@pytest.mark.version('>=2.5.0')
|
||||
|
@ -37,7 +37,7 @@ test_script_1 = """
|
||||
commit;
|
||||
"""
|
||||
|
||||
act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1)
|
||||
act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1, charset='win1251')
|
||||
|
||||
expected_stdout_1 = """
|
||||
CONNECTION_CSET WIN1251
|
||||
|
@ -37,7 +37,7 @@ test_script_1 = """
|
||||
commit;
|
||||
|
||||
-- show proc;
|
||||
set width dep_nm 10;
|
||||
set width dep_name 10;
|
||||
set width dep_on 10;
|
||||
set width dep_on_type 20;
|
||||
set list on;
|
||||
@ -54,14 +54,18 @@ test_script_1 = """
|
||||
act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1)
|
||||
|
||||
expected_stdout_1 = """
|
||||
DEP_NAME P1
|
||||
DEP_ON WIN1250
|
||||
DEP_ON_TYPE COLLATION
|
||||
DEP_NAME P1
|
||||
DEP_ON WIN1250
|
||||
DEP_ON_TYPE COLLATION
|
||||
|
||||
DEP_NAME P2
|
||||
DEP_ON WIN1250
|
||||
DEP_ON_TYPE COLLATION
|
||||
"""
|
||||
DEP_NAME P1
|
||||
DEP_ON UTF8
|
||||
DEP_ON_TYPE COLLATION
|
||||
|
||||
DEP_NAME P2
|
||||
DEP_ON WIN1250
|
||||
DEP_ON_TYPE COLLATION
|
||||
"""
|
||||
|
||||
@pytest.mark.version('>=3.0')
|
||||
def test_1(act_1: Action):
|
||||
|
@ -42,12 +42,12 @@ test_script_1 = """
|
||||
act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1)
|
||||
|
||||
expected_stdout_1 = """
|
||||
ID 1
|
||||
OPDATE 31-DEC-2000
|
||||
ID 1
|
||||
OPDATE 2000-12-31 00:00:00.0000
|
||||
|
||||
ID 2
|
||||
OPDATE 01-JAN-2001
|
||||
"""
|
||||
ID 2
|
||||
OPDATE 2001-01-01 00:00:00.0000
|
||||
"""
|
||||
|
||||
@pytest.mark.version('>=2.5')
|
||||
def test_1(act_1: Action):
|
||||
|
@ -91,7 +91,7 @@ test_script_1 = """
|
||||
;
|
||||
"""
|
||||
|
||||
act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1)
|
||||
act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1,charset=None)
|
||||
|
||||
expected_stdout_1 = """
|
||||
ID 32765
|
||||
|
@ -32,8 +32,8 @@ test_script_1 = """
|
||||
act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1)
|
||||
|
||||
expected_stdout_1 = """
|
||||
01: sqltype: 520 BLOB Nullable scale: 0 subtype: 1 len: 8 charset: 3 UNICODE_FSS
|
||||
01: sqltype: 520 BLOB Nullable scale: 0 subtype: 1 len: 8 charset: 3 UNICODE_FSS
|
||||
01: sqltype: 520 BLOB Nullable scale: 0 subtype: 1 len: 8 charset: 4 UTF8
|
||||
01: sqltype: 520 BLOB Nullable scale: 0 subtype: 1 len: 8 charset: 4 UTF8
|
||||
"""
|
||||
|
||||
@pytest.mark.version('>=3.0,<4.0')
|
||||
|
@ -91,7 +91,7 @@ test_script_1 = """
|
||||
|
||||
"""
|
||||
|
||||
act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1)
|
||||
act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1, charset='NONE')
|
||||
|
||||
expected_stdout_1 = """
|
||||
N 32739
|
||||
|
@ -159,9 +159,9 @@ act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1)
|
||||
|
||||
expected_stdout_1 = """
|
||||
USER TMP$C3735
|
||||
"""
|
||||
"""
|
||||
|
||||
expected_stderr_1 = """
|
||||
There is no privilege granted in this database
|
||||
Statement failed, SQLSTATE = 28000
|
||||
no permission for INSERT access to TABLE RDB$CHARACTER_SETS
|
||||
Statement failed, SQLSTATE = 28000
|
||||
|
@ -25,7 +25,7 @@ test_script_1 = """
|
||||
execute block as
|
||||
declare d date;
|
||||
begin
|
||||
d = "now";
|
||||
d = 'now';
|
||||
end
|
||||
^
|
||||
"""
|
||||
|
@ -14,7 +14,7 @@ from firebird.qa import db_factory, isql_act, Action
|
||||
# version: 3.0
|
||||
# resources: None
|
||||
|
||||
substitutions_1 = []
|
||||
substitutions_1 = [('PROCEDURE_SOURCE .*', '')]
|
||||
|
||||
init_script_1 = """"""
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#coding:utf-8
|
||||
#
|
||||
# id: bugs.core_4082
|
||||
# title: Wrong value of expected length in the sring right truncation error
|
||||
# title: Wrong value of expected length in the string right truncation error
|
||||
# decription:
|
||||
# NB. Ticket title: Wrong error message (should point out the proper expected length)
|
||||
#
|
||||
|
@ -118,12 +118,11 @@ FROM
|
||||
|
||||
act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1)
|
||||
|
||||
expected_stdout_1 = """PLAN JOIN (T1 NATURAL, T1K INDEX (PK_TABLE_1K), T2K INDEX (PK_TABLE_2K), T3K INDEX (PK_TABLE_3K), T4K INDEX (PK_TABLE_4K), T5K INDEX (PK_TABLE_5K), T6K INDEX (PK_TABLE_6K), T8K INDEX (PK_TABLE_8K), T10K INDEX (PK_TABLE_10K))
|
||||
expected_stdout_1 = """PLAN JOIN (T1 NATURAL, T1K INDEX (PK_TABLE_1K), T2K INDEX (PK_TABLE_2K), T3K INDEX (PK_TABLE_3K), T5K INDEX (PK_TABLE_5K), T4K INDEX (PK_TABLE_4K), T6K INDEX (PK_TABLE_6K), T8K INDEX (PK_TABLE_8K), T10K INDEX (PK_TABLE_10K))
|
||||
|
||||
COUNT
|
||||
============
|
||||
|
||||
1
|
||||
COUNT
|
||||
=====================
|
||||
1
|
||||
"""
|
||||
|
||||
@pytest.mark.version('>=2.0')
|
||||
|
@ -34,7 +34,7 @@ expected_stdout_1 = """
|
||||
RDB$OWNER_NAME SYSDBA
|
||||
RDB$DESCRIPTION <null>
|
||||
RDB$SYSTEM_FLAG 1
|
||||
RDB$SECURITY_CLASS SQL$162
|
||||
RDB$SECURITY_CLASS <null>
|
||||
|
||||
Records affected: 1
|
||||
"""
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -35,18 +35,18 @@ test_script_1 = """
|
||||
act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1)
|
||||
|
||||
expected_stdout_1 = """
|
||||
RDB$ROLE_NAME RDB$ADMIN
|
||||
RDB$OWNER_NAME SYSDBA
|
||||
RDB$DESCRIPTION <null>
|
||||
RDB$SYSTEM_FLAG 1
|
||||
RDB$SECURITY_CLASS SQLnnnn
|
||||
RDB$ROLE_NAME RDB$ADMIN
|
||||
RDB$OWNER_NAME SYSDBA
|
||||
RDB$DESCRIPTION <null>
|
||||
RDB$SYSTEM_FLAG 1
|
||||
RDB$SECURITY_CLASS <null>
|
||||
|
||||
RDB$ROLE_NAME TEST
|
||||
RDB$OWNER_NAME SYSDBA
|
||||
RDB$DESCRIPTION <null>
|
||||
RDB$SYSTEM_FLAG 0
|
||||
RDB$SECURITY_CLASS SQLnnnn
|
||||
"""
|
||||
RDB$ROLE_NAME TEST
|
||||
RDB$OWNER_NAME SYSDBA
|
||||
RDB$DESCRIPTION <null>
|
||||
RDB$SYSTEM_FLAG 0
|
||||
RDB$SECURITY_CLASS SQL$414
|
||||
"""
|
||||
|
||||
@pytest.mark.version('>=3.0,<4.0')
|
||||
def test_1(act_1: Action):
|
||||
|
@ -27,7 +27,7 @@ test_script_1 = """
|
||||
act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1)
|
||||
|
||||
expected_stdout_1 = """
|
||||
D -3.000000000000000
|
||||
D -3
|
||||
"""
|
||||
|
||||
@pytest.mark.version('>=2.5')
|
||||
|
Loading…
Reference in New Issue
Block a user