Partially revert 1bcc065224
This change impacts all other scripts that import those modules, while
those weren't updated.
It will be hard to maintain this list, whilst keeping the entire tree
compliant.
Signed-off-by: Pieter De Gendt <pieter.degendt@basalte.be>
251 lines
7.5 KiB
Python
251 lines
7.5 KiB
Python
#!/usr/bin/env python3
|
|
# Copyright (c) 2023 Intel Corporation
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
"""
|
|
Tests for scl.py functions
|
|
"""
|
|
|
|
import logging
|
|
import sys
|
|
from contextlib import nullcontext
|
|
from importlib import reload
|
|
from unittest import mock
|
|
|
|
import pytest
|
|
import scl
|
|
from pykwalify.errors import SchemaError
|
|
from yaml.scanner import ScannerError
|
|
|
|
TESTDATA_1 = [
|
|
(False,),
|
|
(True,),
|
|
]
|
|
|
|
@pytest.mark.parametrize(
|
|
'fail_c',
|
|
TESTDATA_1,
|
|
ids=['C YAML', 'non-C YAML']
|
|
)
|
|
def test_yaml_imports(fail_c):
|
|
class ImportRaiser:
|
|
def find_spec(self, fullname, path, target=None):
|
|
if fullname == 'yaml.CLoader' and fail_c:
|
|
raise ImportError()
|
|
if fullname == 'yaml.CSafeLoader' and fail_c:
|
|
raise ImportError()
|
|
if fullname == 'yaml.CDumper' and fail_c:
|
|
raise ImportError()
|
|
|
|
modules_mock = sys.modules.copy()
|
|
|
|
if hasattr(modules_mock['yaml'], 'CLoader'):
|
|
del modules_mock['yaml'].CLoader
|
|
del modules_mock['yaml'].CSafeLoader
|
|
del modules_mock['yaml'].CDumper
|
|
|
|
cloader_mock = mock.Mock()
|
|
loader_mock = mock.Mock()
|
|
csafeloader_mock = mock.Mock()
|
|
safeloader_mock = mock.Mock()
|
|
cdumper_mock = mock.Mock()
|
|
dumper_mock = mock.Mock()
|
|
|
|
if not fail_c:
|
|
modules_mock['yaml'].CLoader = cloader_mock
|
|
modules_mock['yaml'].CSafeLoader = csafeloader_mock
|
|
modules_mock['yaml'].CDumper = cdumper_mock
|
|
|
|
modules_mock['yaml'].Loader = loader_mock
|
|
modules_mock['yaml'].SafeLoader = safeloader_mock
|
|
modules_mock['yaml'].Dumper = dumper_mock
|
|
|
|
meta_path_mock = sys.meta_path[:]
|
|
meta_path_mock.insert(0, ImportRaiser())
|
|
|
|
with mock.patch.dict('sys.modules', modules_mock, clear=True), \
|
|
mock.patch('sys.meta_path', meta_path_mock):
|
|
reload(scl)
|
|
|
|
assert sys.modules['scl'].Loader == loader_mock if fail_c else \
|
|
cloader_mock
|
|
|
|
assert sys.modules['scl'].SafeLoader == safeloader_mock if fail_c else \
|
|
csafeloader_mock
|
|
|
|
assert sys.modules['scl'].Dumper == dumper_mock if fail_c else \
|
|
cdumper_mock
|
|
|
|
import yaml
|
|
reload(yaml)
|
|
|
|
|
|
TESTDATA_2 = [
|
|
(False, logging.CRITICAL, []),
|
|
(True, None, ['can\'t import pykwalify; won\'t validate YAML']),
|
|
]
|
|
|
|
@pytest.mark.parametrize(
|
|
'fail_pykwalify, log_level, expected_logs',
|
|
TESTDATA_2,
|
|
ids=['pykwalify OK', 'no pykwalify']
|
|
)
|
|
def test_pykwalify_import(caplog, fail_pykwalify, log_level, expected_logs):
|
|
class ImportRaiser:
|
|
def find_spec(self, fullname, path, target=None):
|
|
if fullname == 'pykwalify.core' and fail_pykwalify:
|
|
raise ImportError()
|
|
|
|
modules_mock = sys.modules.copy()
|
|
modules_mock['pykwalify'] = None if fail_pykwalify else \
|
|
modules_mock['pykwalify']
|
|
|
|
meta_path_mock = sys.meta_path[:]
|
|
meta_path_mock.insert(0, ImportRaiser())
|
|
|
|
with mock.patch.dict('sys.modules', modules_mock, clear=True), \
|
|
mock.patch('sys.meta_path', meta_path_mock):
|
|
reload(scl)
|
|
|
|
if log_level:
|
|
assert logging.getLogger('pykwalify.core').level == log_level
|
|
|
|
assert all([log in caplog.text for log in expected_logs])
|
|
|
|
if fail_pykwalify:
|
|
assert scl._yaml_validate(None, None) is None
|
|
assert scl._yaml_validate(mock.Mock(), mock.Mock()) is None
|
|
|
|
reload(scl)
|
|
|
|
|
|
TESTDATA_3 = [
|
|
(False),
|
|
(True),
|
|
]
|
|
|
|
@pytest.mark.parametrize(
|
|
'fail_parsing',
|
|
TESTDATA_3,
|
|
ids=['ok', 'parsing error']
|
|
)
|
|
def test_yaml_load(caplog, fail_parsing):
|
|
result_mock = mock.Mock()
|
|
|
|
def mock_load(*args, **kwargs):
|
|
if fail_parsing:
|
|
context_mark = mock.Mock()
|
|
problem_mark = mock.Mock()
|
|
type(context_mark).args = mock.PropertyMock(return_value=[])
|
|
type(context_mark).name = 'dummy context mark'
|
|
type(context_mark).line = 0
|
|
type(context_mark).column = 0
|
|
type(problem_mark).args = mock.PropertyMock(return_value=[])
|
|
type(problem_mark).name = 'dummy problem mark'
|
|
type(problem_mark).line = 0
|
|
type(problem_mark).column = 0
|
|
raise ScannerError(context='dummy context',
|
|
context_mark=context_mark, problem='dummy problem',
|
|
problem_mark=problem_mark, note='Dummy note')
|
|
return result_mock
|
|
|
|
filename = 'dummy/file.yaml'
|
|
|
|
with mock.patch('yaml.load', side_effect=mock_load), \
|
|
mock.patch('builtins.open', mock.mock_open()) as mock_file:
|
|
with pytest.raises(ScannerError) if fail_parsing else nullcontext():
|
|
result = scl.yaml_load(filename)
|
|
|
|
mock_file.assert_called_with('dummy/file.yaml', 'r', encoding='utf-8')
|
|
|
|
if not fail_parsing:
|
|
assert result == result_mock
|
|
else:
|
|
assert 'dummy problem mark:0:0: error: dummy problem' \
|
|
' (note Dummy note context @dummy context mark:0:0' \
|
|
' dummy context)' in caplog.text
|
|
|
|
|
|
|
|
TESTDATA_4 = [
|
|
(True, False, None),
|
|
(False, False, SchemaError),
|
|
(False, True, ScannerError),
|
|
]
|
|
|
|
@pytest.mark.parametrize(
|
|
'validate, fail_load, expected_error',
|
|
TESTDATA_4,
|
|
ids=['successful validation', 'failed validation', 'failed load']
|
|
)
|
|
def test_yaml_load_verify(validate, fail_load, expected_error):
|
|
filename = 'dummy/file.yaml'
|
|
schema_mock = mock.Mock()
|
|
data_mock = mock.Mock()
|
|
|
|
def mock_load(file_name, *args, **kwargs):
|
|
assert file_name == filename
|
|
if fail_load:
|
|
raise ScannerError
|
|
return data_mock
|
|
|
|
def mock_validate(data, schema, *args, **kwargs):
|
|
assert data == data_mock
|
|
assert schema == schema_mock
|
|
if validate:
|
|
return True
|
|
raise SchemaError(u'Schema validation failed.')
|
|
|
|
with mock.patch('scl.yaml_load', side_effect=mock_load), \
|
|
mock.patch('scl._yaml_validate', side_effect=mock_validate), \
|
|
pytest.raises(expected_error) if expected_error else nullcontext():
|
|
res = scl.yaml_load_verify(filename, schema_mock)
|
|
|
|
if validate:
|
|
assert res == data_mock
|
|
|
|
|
|
TESTDATA_5 = [
|
|
(True, True, None),
|
|
(True, False, SchemaError),
|
|
(False, None, None),
|
|
]
|
|
|
|
@pytest.mark.parametrize(
|
|
'schema_exists, validate, expected_error',
|
|
TESTDATA_5,
|
|
ids=['successful validation', 'failed validation', 'no schema']
|
|
)
|
|
def test_yaml_validate(schema_exists, validate, expected_error):
|
|
data_mock = mock.Mock()
|
|
schema_mock = mock.Mock() if schema_exists else None
|
|
|
|
def mock_validate(raise_exception, *args, **kwargs):
|
|
assert raise_exception
|
|
if validate:
|
|
return True
|
|
raise SchemaError(u'Schema validation failed.')
|
|
|
|
def mock_core(source_data, schema_data, *args, **kwargs):
|
|
assert source_data == data_mock
|
|
assert schema_data == schema_mock
|
|
return mock.Mock(validate=mock_validate)
|
|
|
|
core_mock = mock.Mock(side_effect=mock_core)
|
|
|
|
with mock.patch('pykwalify.core.Core', core_mock), \
|
|
pytest.raises(expected_error) if expected_error else nullcontext():
|
|
scl._yaml_validate(data_mock, schema_mock)
|
|
|
|
if schema_exists:
|
|
core_mock.assert_called_once()
|
|
else:
|
|
core_mock.assert_not_called()
|
|
|
|
|
|
def test_yaml_load_empty_file(tmp_path):
|
|
quarantine_file = tmp_path / 'empty_quarantine.yml'
|
|
quarantine_file.write_text("# yaml file without data")
|
|
with pytest.raises(scl.EmptyYamlFileException):
|
|
scl.yaml_load_verify(quarantine_file, None)
|