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