zephyr/scripts/tests/twister/test_cmakecache.py

273 lines
6.8 KiB
Python

#!/usr/bin/env python3
# Copyright (c) 2023 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
"""
Tests for cmakecache.py classes' methods
"""
import mock
import pytest
from contextlib import nullcontext
from twisterlib.cmakecache import CMakeCacheEntry, CMakeCache
TESTDATA_1 = [
('ON', True),
('YES', True),
('TRUE', True),
('Y', True),
('OFF', False),
('NO', False),
('FALSE', False),
('N', False),
('IGNORE', False),
('NOTFOUND', False),
('', False),
('DUMMY-NOTFOUND', False),
('1', True),
('0', False),
('I AM NOT A PROPER VALUE', ValueError),
]
@pytest.mark.parametrize(
'cmake_bool, expected_bool',
TESTDATA_1,
ids=[t[0] for t in TESTDATA_1]
)
def test_cmakecacheentry_to_bool(cmake_bool, expected_bool):
with pytest.raises(expected_bool) if \
not isinstance(expected_bool, bool) else nullcontext() as exception:
b = CMakeCacheEntry._to_bool(cmake_bool)
if exception is None:
assert b == expected_bool
else:
assert str(exception.value) == f'invalid bool {cmake_bool}'
TESTDATA_2 = [
(
'// I am a comment',
None
),
(
'# I am a comment too',
None
),
(
' \r\n ',
None
),
(
'DUMMY:WRONG_TYPE=???',
None
),
(
'DUMMY_VALUE_NAME1:STRING=I am a dummy string',
CMakeCacheEntry('DUMMY_VALUE_NAME1', 'I am a dummy string')
),
(
'DUMMY_VALUE_NAME2:STRING=list_el1;list_el2;list_el3',
CMakeCacheEntry(
'DUMMY_VALUE_NAME2',
['list_el1', 'list_el2', 'list_el3']
)
),
(
'DUMMY_VALUE_NAME3:INTERNAL=I am a dummy internal string',
CMakeCacheEntry('DUMMY_VALUE_NAME3', 'I am a dummy internal string')),
(
'DUMMY_VALUE_NAME4:INTERNAL=list_el1;list_el2',
CMakeCacheEntry('DUMMY_VALUE_NAME4', ['list_el1', 'list_el2'])
),
(
'DUMMY_VALUE_NAME5:FILEPATH=/path/to/dir',
CMakeCacheEntry('DUMMY_VALUE_NAME5', '/path/to/dir')
),
(
'DUMMY_VALUE_NAME6:PATH=/path/to/dir/file.txt',
CMakeCacheEntry('DUMMY_VALUE_NAME6', '/path/to/dir/file.txt')),
(
'DUMMY_VALUE_NAME7:BOOL=Y',
CMakeCacheEntry('DUMMY_VALUE_NAME7', True)
),
(
'DUMMY_VALUE_NAME8:BOOL=FALSE',
CMakeCacheEntry('DUMMY_VALUE_NAME8', False)
),
(
'DUMMY_VALUE_NAME9:BOOL=NOT_A_BOOL',
ValueError(
(
'invalid bool NOT_A_BOOL',
'on line 7: DUMMY_VALUE_NAME9:BOOL=NOT_A_BOOL'
)
)
),
]
@pytest.mark.parametrize(
'cmake_line, expected',
TESTDATA_2,
ids=[
'// comment',
'# comment',
'whitespace',
'unrecognised type',
'string',
'string list',
'internal string',
'internal list',
'filepath',
'path',
'true bool',
'false bool',
'not a bool'
]
)
def test_cmakecacheentry_from_line(cmake_line, expected):
cmake_line_number = 7
with pytest.raises(type(expected)) if \
isinstance(expected, Exception) else nullcontext() as exception:
entry = CMakeCacheEntry.from_line(cmake_line, cmake_line_number)
if exception is not None:
assert repr(exception.value) == repr(expected)
return
if expected is None:
assert entry is None
return
assert entry.name == expected.name
assert entry.value == expected.value
TESTDATA_3 = [
(
CMakeCacheEntry('DUMMY_NAME1', 'dummy value'),
'CMakeCacheEntry(name=DUMMY_NAME1, value=dummy value)'
),
(
CMakeCacheEntry('DUMMY_NAME2', False),
'CMakeCacheEntry(name=DUMMY_NAME2, value=False)'
)
]
@pytest.mark.parametrize(
'cmake_cache_entry, expected',
TESTDATA_3,
ids=['string value', 'bool value']
)
def test_cmakecacheentry_str(cmake_cache_entry, expected):
assert str(cmake_cache_entry) == expected
def test_cmakecache_load():
file_data = (
'DUMMY_NAME1:STRING=First line\n'
'//Comment on the second line\n'
'DUMMY_NAME2:STRING=Third line\n'
'DUMMY_NAME3:STRING=Fourth line\n'
)
with mock.patch('builtins.open', mock.mock_open(read_data=file_data)):
cache = CMakeCache.from_file('dummy/path/CMakeCache.txt')
assert cache.cache_file == 'dummy/path/CMakeCache.txt'
expected = [
('DUMMY_NAME1', 'First line'),
('DUMMY_NAME2', 'Third line'),
('DUMMY_NAME3', 'Fourth line')
]
for expect in reversed(expected):
item = cache._entries.popitem()
assert item[0] == expect[0]
assert item[1].name == expect[0]
assert item[1].value == expect[1]
def test_cmakecache_get():
file_data = 'DUMMY_NAME:STRING=Dummy value'
with mock.patch('builtins.open', mock.mock_open(read_data=file_data)):
cache = CMakeCache.from_file('dummy/path/CMakeCache.txt')
good_val = cache.get('DUMMY_NAME')
assert good_val == 'Dummy value'
bad_val = cache.get('ANOTHER_NAME')
assert bad_val is None
bad_val = cache.get('ANOTHER_NAME', default='No such value')
assert bad_val == 'No such value'
TESTDATA_4 = [
('STRING=el1;el2;el3;el4', True, ['el1', 'el2', 'el3', 'el4']),
('STRING=dummy value', True, ['dummy value']),
('STRING=', True, []),
('BOOL=True', True, RuntimeError),
('STRING=dummy value', False, []),
]
@pytest.mark.parametrize(
'value, correct_get, expected',
TESTDATA_4,
ids=['list', 'single value', 'empty', 'exception', 'get failure']
)
def test_cmakecache_get_list(value, correct_get, expected):
file_data = f'DUMMY_NAME:{value}'
with mock.patch('builtins.open', mock.mock_open(read_data=file_data)):
cache = CMakeCache.from_file('dummy/path/CMakeCache.txt')
with pytest.raises(expected) if \
isinstance(expected, type) and issubclass(expected, Exception) else \
nullcontext() as exception:
res = cache.get_list('DUMMY_NAME') if \
correct_get else cache.get_list('ANOTHER_NAME')
if exception is None:
assert res == expected
def test_cmakecache_dunders():
file_data = f'DUMMY_NAME:STRING=dummy value'
with mock.patch('builtins.open', mock.mock_open(read_data=file_data)):
cache = CMakeCache.from_file('dummy/path/CMakeCache.txt')
assert len(list(cache.__iter__())) == 1
cache.__setitem__(
'ANOTHER_NAME',
CMakeCacheEntry('ANOTHER_NAME', 'another value')
)
assert cache.__contains__('ANOTHER_NAME')
assert cache.__getitem__('ANOTHER_NAME') == 'another value'
cache.__delitem__('ANOTHER_NAME')
assert not cache.__contains__('ANOTHER_NAME')
assert len(list(cache.__iter__())) == 1
with pytest.raises(TypeError):
cache.__setitem__('WRONG_TYPE', 'Yet Another Dummy Value')