1#!/usr/bin/env python3 2# Copyright (c) 2024 Intel Corporation 3# Copyright (c) 2024 Arm Limited (or its affiliates). All rights reserved. 4# 5# SPDX-License-Identifier: Apache-2.0 6""" 7Tests for config_parser.py 8""" 9 10import os 11from contextlib import nullcontext 12from unittest import mock 13 14import pytest 15import scl 16from twisterlib.config_parser import ( 17 ConfigurationError, 18 TwisterConfigParser, 19 extract_fields_from_arg_list, 20) 21 22 23def test_extract_single_field_from_string_argument(): 24 target_fields = {"FIELD1"} 25 arg_list = "FIELD1=value1 FIELD2=value2 FIELD3=value3" 26 extracted_fields, other_fields = extract_fields_from_arg_list( 27 target_fields, arg_list) 28 29 assert extracted_fields == {"FIELD1": ["value1"]} 30 assert other_fields == ["FIELD2=value2", "FIELD3=value3"] 31 32 33def test_no_fields_to_extract(): 34 target_fields = set() 35 arg_list = "arg1 arg2 arg3" 36 37 extracted_fields, other_fields = extract_fields_from_arg_list( 38 target_fields, arg_list) 39 40 assert extracted_fields == {} 41 assert other_fields == ["arg1", "arg2", "arg3" ] 42 43 44def test_missing_fields(): 45 target_fields = {"CONF_FILE", "OVERLAY_CONFIG", "DTC_OVERLAY_FILE"} 46 arg_list = "arg1 arg2 arg3" 47 extracted_fields, other_fields = extract_fields_from_arg_list( 48 target_fields, arg_list) 49 50 assert extracted_fields == {"CONF_FILE": [], "OVERLAY_CONFIG": [], "DTC_OVERLAY_FILE": []} 51 assert other_fields == ["arg1", "arg2", "arg3" ] 52 53def test_load_yaml_with_extra_args_and_retrieve_scenario_data(zephyr_base): 54 filename = "test_data.yaml" 55 56 yaml_data = ''' 57 tests: 58 scenario1: 59 tags: ['tag1', 'tag2'] 60 extra_args: 61 - '--CONF_FILE=file1.conf' 62 - '--OVERLAY_CONFIG=config1.conf' 63 filter: 'filter1' 64 common: 65 filter: 'filter2' 66 ''' 67 68 loaded_schema = scl.yaml_load( 69 os.path.join(zephyr_base, 'scripts', 'schemas','twister', 'testsuite-schema.yaml') 70 ) 71 72 with mock.patch('builtins.open', mock.mock_open(read_data=yaml_data)): 73 parser = TwisterConfigParser(filename, loaded_schema) 74 parser.load() 75 76 scenario_data = parser.get_scenario('scenario1') 77 scenario_common = parser.common 78 79 assert scenario_data['tags'] == {'tag1', 'tag2'} 80 assert scenario_data['extra_args'] == ['--CONF_FILE=file1.conf', '--OVERLAY_CONFIG=config1.conf'] 81 assert scenario_common == {'filter': 'filter2'} 82 83 84def test_default_values(zephyr_base): 85 filename = "test_data.yaml" 86 87 yaml_data = ''' 88 tests: 89 scenario1: 90 tags: 'tag1' 91 extra_args: '' 92 ''' 93 94 loaded_schema = scl.yaml_load( 95 os.path.join(zephyr_base, 'scripts', 'schemas', 'twister','testsuite-schema.yaml') 96 ) 97 98 with mock.patch('builtins.open', mock.mock_open(read_data=yaml_data)): 99 parser = TwisterConfigParser(filename, loaded_schema) 100 parser.load() 101 102 expected_scenario_data = { 'type': 'integration', 103 'extra_args': [], 104 'extra_configs': [], 105 'extra_conf_files': [], 106 'extra_overlay_confs': [], 107 'extra_dtc_overlay_files': [], 108 'required_snippets': [], 109 'build_only': False, 110 'build_on_all': False, 111 'skip': False, 'slow': False, 112 'timeout': 60, 113 'min_ram': 8, 114 'modules': [], 115 'depends_on': set(), 116 'min_flash': 32, 117 'arch_allow': set(), 118 'arch_exclude': set(), 119 'extra_sections': [], 120 'integration_platforms': [], 121 'ignore_faults': False, 122 'ignore_qemu_crash': False, 123 'testcases': [], 124 'platform_type': [], 125 'platform_exclude': set(), 126 'platform_allow': set(), 127 'platform_key': [], 128 'toolchain_exclude': set(), 129 'toolchain_allow': set(), 130 'filter': '', 131 'levels': [], 132 'harness': 'test', 133 'harness_config': {}, 134 'seed': 0, 'sysbuild': False 135 } 136 137 assert expected_scenario_data.items() <= expected_scenario_data.items() 138 139@pytest.mark.parametrize( 140 'value, typestr, expected, expected_warning', 141 [ 142 (' hello ', 'str', 'hello', None), 143 ('3.14', 'float', 3.14, None), 144 ('10', 'int', 10, None), 145 ('True', 'bool', 'True', None), # do-nothing cast 146 ('key: val', 'map', 'key: val', None), # do-nothing cast 147 ('test', 'int', ValueError, None), 148 ('test', 'unknown', ConfigurationError, None), 149 ([ '1', '2', '3' ], 'set', { '1', '2', '2','3' }, None), 150 ], 151 ids=['str to str', 'str to float', 'str to int', 'str to bool', 'str to map', 152 'invalid', 'to unknown', "list to set"] 153) 154 155def test_cast_value(zephyr_base, value, typestr, expected, expected_warning): 156 loaded_schema = scl.yaml_load( 157 os.path.join(zephyr_base, 'scripts', 'schemas', 'twister','testsuite-schema.yaml') 158 ) 159 160 parser = TwisterConfigParser("config.yaml", loaded_schema) 161 with mock.patch('warnings.warn') as warn_mock: 162 with pytest.raises(expected) if isinstance(expected, type) and issubclass(expected, Exception) else nullcontext(): 163 result = parser._cast_value(value, typestr) 164 assert result == expected 165 if expected_warning: 166 warn_mock.assert_called_once_with(*expected_warning, stacklevel=mock.ANY) 167 else: 168 warn_mock.assert_not_called() 169 170def test_load_invalid_test_config_yaml(zephyr_base): 171 filename = "test_data.yaml" 172 173 yaml_data = ''' 174 gibberish data 175 ''' 176 177 loaded_schema = scl.yaml_load( 178 os.path.join(zephyr_base, 'scripts', 'schemas','twister', 'test-config-schema.yaml') 179 ) 180 181 with mock.patch('builtins.open', mock.mock_open(read_data=yaml_data)): 182 parser = TwisterConfigParser(filename, loaded_schema) 183 with pytest.raises(Exception): 184 parser.load() 185 186 187def test_load_yaml_with_no_scenario_data(zephyr_base): 188 filename = "test_data.yaml" 189 190 yaml_data = ''' 191 tests: 192 common: 193 extra_args: '--CONF_FILE=file2.conf --OVERLAY_CONFIG=config2.conf' 194 ''' 195 196 loaded_schema = scl.yaml_load( 197 os.path.join(zephyr_base, 'scripts', 'schemas','twister', 'testsuite-schema.yaml') 198 ) 199 200 with mock.patch('builtins.open', mock.mock_open(read_data=yaml_data)): 201 parser = TwisterConfigParser(filename, loaded_schema) 202 parser.load() 203 204 with pytest.raises(KeyError): 205 scenario_data = parser.get_scenario('scenario1') 206 assert scenario_data is None 207