Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
api_test.py
00001 """Tests for the toolchain sub-system""" 00002 import sys 00003 import os 00004 from string import printable 00005 from copy import deepcopy 00006 from mock import MagicMock, patch 00007 from hypothesis import given, settings 00008 from hypothesis.strategies import text, lists, fixed_dictionaries, booleans 00009 00010 ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", 00011 "..")) 00012 sys.path.insert(0, ROOT) 00013 00014 from tools.toolchains import ( 00015 TOOLCHAIN_CLASSES, 00016 TOOLCHAIN_PATHS, 00017 mbedToolchain, 00018 ) 00019 from tools.resources import LEGACY_TOOLCHAIN_NAMES, Resources, FileType 00020 from tools.targets import TARGET_MAP, set_targets_json_location 00021 from tools.notifier.mock import MockNotifier 00022 00023 ALPHABET = [char for char in printable if char not in [u'.', u'/', u'\\']] 00024 00025 00026 @patch('tools.toolchains.arm.run_cmd') 00027 def test_arm_version_check(_run_cmd): 00028 set_targets_json_location() 00029 _run_cmd.return_value = (""" 00030 Product: ARM Compiler 5.06 00031 Component: ARM Compiler 5.06 update 5 (build 528) 00032 Tool: armcc [4d3621] 00033 """, "", 0) 00034 notifier = MockNotifier() 00035 toolchain = TOOLCHAIN_CLASSES["ARM"](TARGET_MAP["K64F"], notify=notifier) 00036 toolchain.version_check() 00037 assert notifier.messages == [] 00038 _run_cmd.return_value = (""" 00039 Product: MDK Professional 5.22 00040 Component: ARM Compiler 5.06 update 5 (build 528) 00041 Tool: armcc [4d3621] 00042 """, "", 0) 00043 toolchain.version_check() 00044 assert notifier.messages == [] 00045 _run_cmd.return_value = (""" 00046 Product: ARM Compiler 00047 Component: ARM Compiler 00048 Tool: armcc [4d3621] 00049 """, "", 0) 00050 toolchain.version_check() 00051 assert len(notifier.messages) == 1 00052 00053 00054 @patch('tools.toolchains.iar.run_cmd') 00055 def test_iar_version_check(_run_cmd): 00056 set_targets_json_location() 00057 _run_cmd.return_value = (""" 00058 IAR ANSI C/C++ Compiler V7.80.1.28/LNX for ARM 00059 """, "", 0) 00060 notifier = MockNotifier() 00061 toolchain = TOOLCHAIN_CLASSES["IAR"](TARGET_MAP["K64F"], notify=notifier) 00062 toolchain.version_check() 00063 assert notifier.messages == [] 00064 _run_cmd.return_value = (""" 00065 IAR ANSI C/C++ Compiler V/LNX for ARM 00066 """, "", 0) 00067 toolchain.version_check() 00068 assert len(notifier.messages) == 1 00069 _run_cmd.return_value = (""" 00070 IAR ANSI C/C++ Compiler V/8.80LNX for ARM 00071 """, "", 0) 00072 toolchain.version_check() 00073 assert len(notifier.messages) == 2 00074 00075 00076 @patch('tools.toolchains.gcc.run_cmd') 00077 def test_gcc_version_check(_run_cmd): 00078 set_targets_json_location() 00079 _run_cmd.return_value = (""" 00080 arm-none-eabi-gcc (Arch Repository) 6.4.4 00081 Copyright (C) 2018 Free Software Foundation, Inc. 00082 This is free software; see the source for copying conditions. There is NO 00083 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00084 """, "", 0) 00085 notifier = MockNotifier() 00086 toolchain = TOOLCHAIN_CLASSES["GCC_ARM"]( 00087 TARGET_MAP["K64F"], notify=notifier) 00088 toolchain.version_check() 00089 assert notifier.messages == [] 00090 _run_cmd.return_value = (""" 00091 arm-none-eabi-gcc (Arch Repository) 8.1.0 00092 Copyright (C) 2018 Free Software Foundation, Inc. 00093 This is free software; see the source for copying conditions. There is NO 00094 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00095 """, "", 0) 00096 toolchain.version_check() 00097 assert len(notifier.messages) == 1 00098 _run_cmd.return_value = (""" 00099 arm-none-eabi-gcc (Arch Repository) 00100 Copyright (C) 2018 Free Software Foundation, Inc. 00101 This is free software; see the source for copying conditions. There is NO 00102 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00103 """, "", 0) 00104 toolchain.version_check() 00105 assert len(notifier.messages) == 2 00106 00107 00108 @given(fixed_dictionaries({ 00109 'common': lists(text()), 00110 'c': lists(text()), 00111 'cxx': lists(text()), 00112 'asm': lists(text()), 00113 'ld': lists(text())}), 00114 lists(text(min_size=1, alphabet=ALPHABET), min_size=1)) 00115 def test_toolchain_profile_c (profile, source_file): 00116 """Test that the appropriate profile parameters are passed to the 00117 C compiler""" 00118 filename = deepcopy(source_file) 00119 filename[-1] += ".c" 00120 to_compile = os.path.join(*filename) 00121 set_targets_json_location() 00122 with patch('os.mkdir') as _mkdir: 00123 for _, tc_class in TOOLCHAIN_CLASSES.items(): 00124 toolchain = tc_class(TARGET_MAP["K64F"], build_profile=profile, 00125 notify=MockNotifier()) 00126 toolchain.inc_md5 = "" 00127 toolchain.build_dir = "" 00128 toolchain.config = MagicMock(app_config_location=None) 00129 for parameter in profile['c'] + profile['common']: 00130 assert any(parameter in cmd for cmd in toolchain.cc), \ 00131 "Toolchain %s did not propagate arg %s" % (toolchain.name, 00132 parameter) 00133 compile_command = toolchain.compile_command(to_compile, 00134 to_compile + ".o", []) 00135 for parameter in profile['c'] + profile['common']: 00136 assert any(parameter in cmd for cmd in compile_command), \ 00137 "Toolchain %s did not propagate arg %s" % (toolchain.name, 00138 parameter) 00139 00140 @given(fixed_dictionaries({ 00141 'common': lists(text()), 00142 'c': lists(text()), 00143 'cxx': lists(text()), 00144 'asm': lists(text()), 00145 'ld': lists(text())}), 00146 lists(text(min_size=1, alphabet=ALPHABET), min_size=1)) 00147 def test_toolchain_profile_cpp (profile, source_file): 00148 """Test that the appropriate profile parameters are passed to the 00149 C++ compiler""" 00150 filename = deepcopy(source_file) 00151 filename[-1] += ".cpp" 00152 to_compile = os.path.join(*filename) 00153 with patch('os.mkdir') as _mkdir: 00154 for _, tc_class in TOOLCHAIN_CLASSES.items(): 00155 toolchain = tc_class(TARGET_MAP["K64F"], build_profile=profile, 00156 notify=MockNotifier()) 00157 toolchain.inc_md5 = "" 00158 toolchain.build_dir = "" 00159 toolchain.config = MagicMock(app_config_location=None) 00160 for parameter in profile['cxx'] + profile['common']: 00161 assert any(parameter in cmd for cmd in toolchain.cppc), \ 00162 "Toolchain %s did not propagate arg %s" % (toolchain.name, 00163 parameter) 00164 compile_command = toolchain.compile_command(to_compile, 00165 to_compile + ".o", []) 00166 for parameter in profile['cxx'] + profile['common']: 00167 assert any(parameter in cmd for cmd in compile_command), \ 00168 "Toolchain %s did not propagate arg %s" % (toolchain.name, 00169 parameter) 00170 00171 @given(fixed_dictionaries({ 00172 'common': lists(text()), 00173 'c': lists(text()), 00174 'cxx': lists(text()), 00175 'asm': lists(text()), 00176 'ld': lists(text())}), 00177 lists(text(min_size=1, alphabet=ALPHABET), min_size=1)) 00178 def test_toolchain_profile_asm (profile, source_file): 00179 """Test that the appropriate profile parameters are passed to the 00180 Assembler""" 00181 filename = deepcopy(source_file) 00182 filename[-1] += ".s" 00183 to_compile = os.path.join(*filename) 00184 with patch('os.mkdir') as _mkdir: 00185 for _, tc_class in TOOLCHAIN_CLASSES.items(): 00186 toolchain = tc_class(TARGET_MAP["K64F"], build_profile=profile, 00187 notify=MockNotifier()) 00188 toolchain.inc_md5 = "" 00189 toolchain.build_dir = "" 00190 toolchain.config = MagicMock() 00191 toolchain.config.get_config_data_macros.return_value = [] 00192 for parameter in profile['asm']: 00193 assert any(parameter in cmd for cmd in toolchain.asm), \ 00194 "Toolchain %s did not propagate arg %s" % (toolchain.name, 00195 parameter) 00196 compile_command = toolchain.compile_command(to_compile, 00197 to_compile + ".o", []) 00198 if not compile_command: 00199 assert compile_command, to_compile 00200 for parameter in profile['asm']: 00201 assert any(parameter in cmd for cmd in compile_command), \ 00202 "Toolchain %s did not propagate arg %s" % (toolchain.name, 00203 parameter) 00204 00205 for name, Class in TOOLCHAIN_CLASSES.items(): 00206 CLS = Class(TARGET_MAP["K64F"], notify=MockNotifier()) 00207 assert name == CLS.name or name == LEGACY_TOOLCHAIN_NAMES[CLS.name] 00208 00209 @given(fixed_dictionaries({ 00210 'common': lists(text()), 00211 'c': lists(text()), 00212 'cxx': lists(text()), 00213 'asm': lists(text()), 00214 'ld': lists(text(min_size=1))}), 00215 lists(text(min_size=1, alphabet=ALPHABET), min_size=1)) 00216 def test_toolchain_profile_ld (profile, source_file): 00217 """Test that the appropriate profile parameters are passed to the 00218 Linker""" 00219 filename = deepcopy(source_file) 00220 filename[-1] += ".o" 00221 to_compile = os.path.join(*filename) 00222 with patch('os.mkdir') as _mkdir,\ 00223 patch('tools.toolchains.mbedToolchain.default_cmd') as _dflt_cmd: 00224 for _, tc_class in TOOLCHAIN_CLASSES.items(): 00225 toolchain = tc_class(TARGET_MAP["K64F"], build_profile=profile, 00226 notify=MockNotifier()) 00227 toolchain.RESPONSE_FILES = False 00228 toolchain.inc_md5 = "" 00229 toolchain.build_dir = "" 00230 for parameter in profile['ld']: 00231 assert any(parameter in cmd for cmd in toolchain.ld), \ 00232 "Toolchain %s did not propagate arg %s" % (toolchain.name, 00233 parameter) 00234 toolchain.link(to_compile + ".elf", [to_compile], [], [], None) 00235 compile_cmd = _dflt_cmd.call_args_list 00236 if not compile_cmd: 00237 assert compile_cmd, to_compile 00238 for parameter in profile['ld']: 00239 assert any(parameter in cmd[0][0] for cmd in compile_cmd), \ 00240 "Toolchain %s did not propagate arg %s" % (toolchain.name, 00241 parameter) 00242 00243 for name, Class in TOOLCHAIN_CLASSES.items(): 00244 CLS = Class(TARGET_MAP["K64F"], notify=MockNotifier()) 00245 assert name == CLS.name or name == LEGACY_TOOLCHAIN_NAMES[CLS.name] 00246 00247 00248 @given(lists(text(alphabet=ALPHABET, min_size=1), min_size=1)) 00249 def test_detect_duplicates(filenames): 00250 c_sources = [os.path.join(name, "dupe.c") for name in filenames] 00251 s_sources = [os.path.join(name, "dupe.s") for name in filenames] 00252 cpp_sources = [os.path.join(name, "dupe.cpp") for name in filenames] 00253 notify = MockNotifier() 00254 res = Resources(notify) 00255 res.add_files_to_type(FileType.C_SRC, c_sources) 00256 res.add_files_to_type(FileType.ASM_SRC, s_sources) 00257 res.add_files_to_type(FileType.CPP_SRC, cpp_sources) 00258 assert res.detect_duplicates() == 1,\ 00259 "Not Enough duplicates found" 00260 00261 notification = notify.messages[0] 00262 assert "dupe.o" in notification["message"] 00263 assert "dupe.s" in notification["message"] 00264 assert "dupe.c" in notification["message"] 00265 assert "dupe.cpp" in notification["message"] 00266 00267 @given(text(alphabet=ALPHABET + [os.sep], min_size=1)) 00268 @given(booleans()) 00269 @given(booleans()) 00270 @settings(max_examples=20) 00271 def test_path_specified_gcc(gcc_loc, exists_at_loc, exists_in_path): 00272 with patch('tools.toolchains.gcc.exists') as _exists: 00273 with patch('tools.toolchains.gcc.find_executable') as _find: 00274 _exists.return_value = exists_at_loc 00275 _find.return_value = exists_in_path 00276 TOOLCHAIN_PATHS['GCC_ARM'] = gcc_loc 00277 toolchain_class = TOOLCHAIN_CLASSES["GCC_ARM"] 00278 found_p = toolchain_class.check_executable() 00279 assert found_p == (exists_at_loc or exists_in_path) 00280 if exists_at_loc: 00281 assert TOOLCHAIN_PATHS['GCC_ARM'] == gcc_loc 00282 elif exists_in_path: 00283 assert TOOLCHAIN_PATHS['GCC_ARM'] == ''
Generated on Tue Aug 9 2022 00:37:00 by
1.7.2