1#!/usr/bin/env python3 2# Copyright (c) 2023 Intel Corporation 3# 4# SPDX-License-Identifier: Apache-2.0 5""" 6Tests for cmakecache.py classes' methods 7""" 8 9import mock 10import pytest 11 12from contextlib import nullcontext 13 14from twisterlib.cmakecache import CMakeCacheEntry, CMakeCache 15 16 17TESTDATA_1 = [ 18 ('ON', True), 19 ('YES', True), 20 ('TRUE', True), 21 ('Y', True), 22 ('OFF', False), 23 ('NO', False), 24 ('FALSE', False), 25 ('N', False), 26 ('IGNORE', False), 27 ('NOTFOUND', False), 28 ('', False), 29 ('DUMMY-NOTFOUND', False), 30 ('1', True), 31 ('0', False), 32 ('I AM NOT A PROPER VALUE', ValueError), 33] 34 35 36@pytest.mark.parametrize( 37 'cmake_bool, expected_bool', 38 TESTDATA_1, 39 ids=[t[0] for t in TESTDATA_1] 40) 41def test_cmakecacheentry_to_bool(cmake_bool, expected_bool): 42 with pytest.raises(expected_bool) if \ 43 not isinstance(expected_bool, bool) else nullcontext() as exception: 44 b = CMakeCacheEntry._to_bool(cmake_bool) 45 46 if exception is None: 47 assert b == expected_bool 48 else: 49 assert str(exception.value) == f'invalid bool {cmake_bool}' 50 51 52TESTDATA_2 = [ 53 ( 54 '// I am a comment', 55 None 56 ), 57 ( 58 '# I am a comment too', 59 None 60 ), 61 ( 62 ' \r\n ', 63 None 64 ), 65 ( 66 'DUMMY:WRONG_TYPE=???', 67 None 68 ), 69 ( 70 'DUMMY_VALUE_NAME1:STRING=I am a dummy string', 71 CMakeCacheEntry('DUMMY_VALUE_NAME1', 'I am a dummy string') 72 ), 73 ( 74 'DUMMY_VALUE_NAME2:STRING=list_el1;list_el2;list_el3', 75 CMakeCacheEntry( 76 'DUMMY_VALUE_NAME2', 77 ['list_el1', 'list_el2', 'list_el3'] 78 ) 79 ), 80 ( 81 'DUMMY_VALUE_NAME3:INTERNAL=I am a dummy internal string', 82 CMakeCacheEntry('DUMMY_VALUE_NAME3', 'I am a dummy internal string')), 83 ( 84 'DUMMY_VALUE_NAME4:INTERNAL=list_el1;list_el2', 85 CMakeCacheEntry('DUMMY_VALUE_NAME4', ['list_el1', 'list_el2']) 86 ), 87 ( 88 'DUMMY_VALUE_NAME5:FILEPATH=/path/to/dir', 89 CMakeCacheEntry('DUMMY_VALUE_NAME5', '/path/to/dir') 90 ), 91 ( 92 'DUMMY_VALUE_NAME6:PATH=/path/to/dir/file.txt', 93 CMakeCacheEntry('DUMMY_VALUE_NAME6', '/path/to/dir/file.txt')), 94 ( 95 'DUMMY_VALUE_NAME7:BOOL=Y', 96 CMakeCacheEntry('DUMMY_VALUE_NAME7', True) 97 ), 98 ( 99 'DUMMY_VALUE_NAME8:BOOL=FALSE', 100 CMakeCacheEntry('DUMMY_VALUE_NAME8', False) 101 ), 102 ( 103 'DUMMY_VALUE_NAME9:BOOL=NOT_A_BOOL', 104 ValueError( 105 ( 106 'invalid bool NOT_A_BOOL', 107 'on line 7: DUMMY_VALUE_NAME9:BOOL=NOT_A_BOOL' 108 ) 109 ) 110 ), 111] 112 113 114@pytest.mark.parametrize( 115 'cmake_line, expected', 116 TESTDATA_2, 117 ids=[ 118 '// comment', 119 '# comment', 120 'whitespace', 121 'unrecognised type', 122 'string', 123 'string list', 124 'internal string', 125 'internal list', 126 'filepath', 127 'path', 128 'true bool', 129 'false bool', 130 'not a bool' 131 ] 132) 133def test_cmakecacheentry_from_line(cmake_line, expected): 134 cmake_line_number = 7 135 136 with pytest.raises(type(expected)) if \ 137 isinstance(expected, Exception) else nullcontext() as exception: 138 entry = CMakeCacheEntry.from_line(cmake_line, cmake_line_number) 139 140 if exception is not None: 141 assert repr(exception.value) == repr(expected) 142 return 143 144 if expected is None: 145 assert entry is None 146 return 147 148 assert entry.name == expected.name 149 assert entry.value == expected.value 150 151 152TESTDATA_3 = [ 153 ( 154 CMakeCacheEntry('DUMMY_NAME1', 'dummy value'), 155 'CMakeCacheEntry(name=DUMMY_NAME1, value=dummy value)' 156 ), 157 ( 158 CMakeCacheEntry('DUMMY_NAME2', False), 159 'CMakeCacheEntry(name=DUMMY_NAME2, value=False)' 160 ) 161] 162 163 164@pytest.mark.parametrize( 165 'cmake_cache_entry, expected', 166 TESTDATA_3, 167 ids=['string value', 'bool value'] 168) 169def test_cmakecacheentry_str(cmake_cache_entry, expected): 170 assert str(cmake_cache_entry) == expected 171 172 173def test_cmakecache_load(): 174 file_data = ( 175 'DUMMY_NAME1:STRING=First line\n' 176 '//Comment on the second line\n' 177 'DUMMY_NAME2:STRING=Third line\n' 178 'DUMMY_NAME3:STRING=Fourth line\n' 179 ) 180 181 with mock.patch('builtins.open', mock.mock_open(read_data=file_data)): 182 cache = CMakeCache.from_file('dummy/path/CMakeCache.txt') 183 184 assert cache.cache_file == 'dummy/path/CMakeCache.txt' 185 186 expected = [ 187 ('DUMMY_NAME1', 'First line'), 188 ('DUMMY_NAME2', 'Third line'), 189 ('DUMMY_NAME3', 'Fourth line') 190 ] 191 192 for expect in reversed(expected): 193 item = cache._entries.popitem() 194 195 assert item[0] == expect[0] 196 assert item[1].name == expect[0] 197 assert item[1].value == expect[1] 198 199 200def test_cmakecache_get(): 201 file_data = 'DUMMY_NAME:STRING=Dummy value' 202 203 with mock.patch('builtins.open', mock.mock_open(read_data=file_data)): 204 cache = CMakeCache.from_file('dummy/path/CMakeCache.txt') 205 206 good_val = cache.get('DUMMY_NAME') 207 208 assert good_val == 'Dummy value' 209 210 bad_val = cache.get('ANOTHER_NAME') 211 212 assert bad_val is None 213 214 bad_val = cache.get('ANOTHER_NAME', default='No such value') 215 216 assert bad_val == 'No such value' 217 218 219TESTDATA_4 = [ 220 ('STRING=el1;el2;el3;el4', True, ['el1', 'el2', 'el3', 'el4']), 221 ('STRING=dummy value', True, ['dummy value']), 222 ('STRING=', True, []), 223 ('BOOL=True', True, RuntimeError), 224 ('STRING=dummy value', False, []), 225] 226 227 228@pytest.mark.parametrize( 229 'value, correct_get, expected', 230 TESTDATA_4, 231 ids=['list', 'single value', 'empty', 'exception', 'get failure'] 232) 233def test_cmakecache_get_list(value, correct_get, expected): 234 file_data = f'DUMMY_NAME:{value}' 235 236 with mock.patch('builtins.open', mock.mock_open(read_data=file_data)): 237 cache = CMakeCache.from_file('dummy/path/CMakeCache.txt') 238 239 with pytest.raises(expected) if \ 240 isinstance(expected, type) and issubclass(expected, Exception) else \ 241 nullcontext() as exception: 242 res = cache.get_list('DUMMY_NAME') if \ 243 correct_get else cache.get_list('ANOTHER_NAME') 244 245 if exception is None: 246 assert res == expected 247 248 249def test_cmakecache_dunders(): 250 file_data = f'DUMMY_NAME:STRING=dummy value' 251 252 with mock.patch('builtins.open', mock.mock_open(read_data=file_data)): 253 cache = CMakeCache.from_file('dummy/path/CMakeCache.txt') 254 255 assert len(list(cache.__iter__())) == 1 256 257 cache.__setitem__( 258 'ANOTHER_NAME', 259 CMakeCacheEntry('ANOTHER_NAME', 'another value') 260 ) 261 262 assert cache.__contains__('ANOTHER_NAME') 263 assert cache.__getitem__('ANOTHER_NAME') == 'another value' 264 265 cache.__delitem__('ANOTHER_NAME') 266 267 assert not cache.__contains__('ANOTHER_NAME') 268 269 assert len(list(cache.__iter__())) == 1 270 271 with pytest.raises(TypeError): 272 cache.__setitem__('WRONG_TYPE', 'Yet Another Dummy Value') 273