def test_toolchain_profile_asm(profile, source_file): """Test that the appropriate profile parameters are passed to the Assembler""" filename = deepcopy(source_file) filename[-1] += ".s" to_compile = os.path.join(*filename) with patch('os.mkdir') as _mkdir: for _, tc_class in TOOLCHAIN_CLASSES.items(): toolchain = tc_class(TARGET_MAP["K64F"], build_profile=profile, notify=MockNotifier()) toolchain.inc_md5 = "" toolchain.build_dir = "" toolchain.config = MagicMock() toolchain.config.get_config_data_macros.return_value = [] for parameter in profile['asm']: assert any(parameter in cmd for cmd in toolchain.asm), \ "Toolchain %s did not propagate arg %s" % (toolchain.name, parameter) compile_command = toolchain.compile_command(to_compile, to_compile + ".o", []) if not compile_command: assert compile_command, to_compile for parameter in profile['asm']: assert any(parameter in cmd for cmd in compile_command), \ "Toolchain %s did not propagate arg %s" % (toolchain.name, parameter) for name, Class in TOOLCHAIN_CLASSES.items(): CLS = Class(TARGET_MAP["K64F"], notify=MockNotifier()) assert name == CLS.name or name == LEGACY_TOOLCHAIN_NAMES[CLS.name]
def test_toolchain_profile_ld(profile, source_file): """Test that the appropriate profile parameters are passed to the Linker""" filename = deepcopy(source_file) filename[-1] += ".o" to_compile = os.path.join(*filename) with patch('os.mkdir') as _mkdir,\ patch('tools.toolchains.mbedToolchain.default_cmd') as _dflt_cmd: for _, tc_class in TOOLCHAIN_CLASSES.items(): toolchain = tc_class(TARGET_MAP["K64F"], build_profile=profile, notify=MockNotifier()) toolchain.RESPONSE_FILES = False toolchain.inc_md5 = "" toolchain.build_dir = "" for parameter in profile['ld']: assert any(parameter in cmd for cmd in toolchain.ld), \ "Toolchain %s did not propagate arg %s" % (toolchain.name, parameter) toolchain.link(to_compile + ".elf", [to_compile], [], [], None) compile_cmd = _dflt_cmd.call_args_list if not compile_cmd: assert compile_cmd, to_compile for parameter in profile['ld']: assert any(parameter in cmd[0][0] for cmd in compile_cmd), \ "Toolchain %s did not propagate arg %s" % (toolchain.name, parameter) for name, Class in TOOLCHAIN_CLASSES.items(): CLS = Class(TARGET_MAP["K64F"], notify=MockNotifier()) assert name == CLS.name or name == LEGACY_TOOLCHAIN_NAMES[CLS.name]
def test_always_complete_build(self, *_): notify = MockNotifier() toolchain = prepare_toolchain(self.src_paths, self.build_path, self.target, self.toolchain_name, notify=notify) res = Resources(MockNotifier()).scan_with_toolchain( self.src_paths, toolchain) toolchain.RESPONSE_FILES=False toolchain.config_processed = True toolchain.config_file = "junk" toolchain.compile_sources(res) assert any('percent' in msg and msg['percent'] == 100.0 for msg in notify.messages if msg)
def test_merge_region_no_fit(self, mock_config, mock_intelhex_offset): """ Test that merge_region_list call fails when part size overflows region size. :param mock_config: config object that is mocked. :param mock_intelhex_offset: mocked intel_hex_offset call. :return: """ max_addr = 87444 # create a dummy hex file with above max_addr mock_intelhex_offset.return_value = IntelHex({0:2, max_addr:0}) # create application and post-application regions and merge. region_application = Region("application", 10000, 86000, True, "random.hex") region_post_application = Region("postapplication", 100000, 90000, False, None) notify = MockNotifier() region_list = [region_application, region_post_application] # path to store the result in, should not get used as we expect exception. res = "./" mock_config.target.restrict_size = 90000 toolexception = False try: merge_region_list(region_list, res, notify, mock_config) except ToolException: toolexception = True except Exception as e: print("%s %s" % (e.message, e.args)) self.assertTrue(toolexception, "Expected ToolException not raised")
def test_build_project_app_config(self, mock_prepare_toolchain, mock_exists, _, __): """ Test that build_project uses app_config correctly :param mock_prepare_toolchain: mock of function prepare_toolchain :param mock_exists: mock of function os.path.exists :param _: mock of function mkdir (not tested) :param __: mock of class Resources (not tested) :return: """ notify = MockNotifier() app_config = "app_config" mock_exists.return_value = False mock_prepare_toolchain().link_program.return_value = 1, 2 mock_prepare_toolchain().config = MagicMock( has_regions=None, name=None, lib_config_data=None, ) mock_prepare_toolchain().config.deliver_into.return_value = (None, None) mock_prepare_toolchain().config.name = None build_project(self.src_paths, self.build_path, self.target, self.toolchain_name, app_config=app_config, notify=notify) args = mock_prepare_toolchain.call_args self.assertTrue('app_config' in args[1], "prepare_toolchain was not called with app_config") self.assertEqual(args[1]['app_config'], app_config, "prepare_toolchain was called with an incorrect app_config")
def test_build_library_no_app_config(self, mock_prepare_toolchain, mock_exists, _, __): """ Test that build_library correctly deals with no app_config :param mock_prepare_toolchain: mock of function prepare_toolchain :param mock_exists: mock of function os.path.exists :param _: mock of function mkdir (not tested) :param __: mock of class Resources (not tested) :return: """ notify = MockNotifier() mock_exists.return_value = False build_library(self.src_paths, self.build_path, self.target, self.toolchain_name, notify=notify) args = mock_prepare_toolchain.call_args self.assertTrue('app_config' in args[1], "prepare_toolchain was not called with app_config") self.assertEqual( args[1]['app_config'], None, "prepare_toolchain was called with an incorrect app_config")
def test_toolchain_profile_c(profile, source_file): """Test that the appropriate profile parameters are passed to the C compiler""" filename = deepcopy(source_file) filename[-1] += ".c" to_compile = os.path.join(*filename) set_targets_json_location() with patch('os.mkdir') as _mkdir: for _, tc_class in TOOLCHAIN_CLASSES.items(): toolchain = tc_class(test_target_map, build_profile=profile, notify=MockNotifier()) toolchain.inc_md5 = "" toolchain.build_dir = "" toolchain.config = MagicMock(app_config_location=None) for parameter in profile['c'] + profile['common']: assert any(parameter in cmd for cmd in toolchain.cc), \ "Toolchain %s did not propagate arg %s" % (toolchain.name, parameter) compile_command = toolchain.compile_command( to_compile, to_compile + ".o", []) for parameter in profile['c'] + profile['common']: assert any(parameter in cmd for cmd in compile_command), \ "Toolchain %s did not propagate arg %s" % (toolchain.name, parameter)
def test_arm_version_check(_run_cmd): set_targets_json_location() _run_cmd.return_value = (""" Product: ARM Compiler 5.06 Component: ARM Compiler 5.06 update 5 (build 528) Tool: armcc [4d3621] """, "", 0) notifier = MockNotifier() toolchain = TOOLCHAIN_CLASSES["ARM"](TARGET_MAP["K64F"], notify=notifier) toolchain.version_check() assert notifier.messages == [] _run_cmd.return_value = (""" Product: MDK Professional 5.22 Component: ARM Compiler 5.06 update 5 (build 528) Tool: armcc [4d3621] """, "", 0) toolchain.version_check() assert notifier.messages == [] _run_cmd.return_value = (""" Product: ARM Compiler Component: ARM Compiler Tool: armcc [4d3621] """, "", 0) toolchain.version_check() assert len(notifier.messages) == 1
def test_gcc_version_check(_run_cmd): set_targets_json_location() _run_cmd.return_value = (""" arm-none-eabi-gcc (Arch Repository) 6.4.4 Copyright (C) 2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. """, "", 0) notifier = MockNotifier() toolchain = TOOLCHAIN_CLASSES["GCC_ARM"]( TARGET_MAP["K64F"], notify=notifier) toolchain.version_check() assert notifier.messages == [] _run_cmd.return_value = (""" arm-none-eabi-gcc (Arch Repository) 8.1.0 Copyright (C) 2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. """, "", 0) toolchain.version_check() assert len(notifier.messages) == 1 _run_cmd.return_value = (""" arm-none-eabi-gcc (Arch Repository) Copyright (C) 2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. """, "", 0) toolchain.version_check() assert len(notifier.messages) == 2
def test_build_project_no_app_config(self, mock_prepare_toolchain, mock_exists, _, __): """ Test that build_project correctly deals with no app_config :param mock_prepare_toolchain: mock of function prepare_toolchain :param mock_exists: mock of function os.path.exists :param _: mock of function mkdir (not tested) :param __: mock of class Resources (not tested) :return: """ notify = MockNotifier() mock_exists.return_value = False # Needed for the unpacking of the returned value mock_prepare_toolchain().link_program.return_value = 1, 2 mock_prepare_toolchain().config = namedtuple( "Config", "has_regions name lib_config_data")(None, None, {}) build_project(self.src_paths, self.build_path, self.target, self.toolchain_name, notify=notify) args = mock_prepare_toolchain.call_args self.assertTrue('app_config' in args[1], "prepare_toolchain was not called with app_config") self.assertEqual(args[1]['app_config'], None, "prepare_toolchain was called with an incorrect app_config")
def test_armc5_version_check(_run_cmd): set_targets_json_location() _run_cmd.return_value = (""" Product: ARM Compiler 5.06 Component: ARM Compiler 5.06 update 5 (build 528) Tool: armcc [4d3621] """, "", 0) notifier = MockNotifier() target_map = TARGET_MAP["K64F"] #We have to add ARMC5 here to supported_toolchains, otherwise the creation of ARM class would fail as it wont find ARMC5 entry in supported_toolchains target_map.supported_toolchains.append("ARMC5") toolchain = TOOLCHAIN_CLASSES["ARM"](target_map, notify=notifier) toolchain.version_check() assert notifier.messages == [] _run_cmd.return_value = (""" Product: MDK Professional 5.22 Component: ARM Compiler 5.06 update 5 (build 528) Tool: armcc [4d3621] """, "", 0) toolchain.version_check() assert notifier.messages == [] _run_cmd.return_value = (""" Product: ARM Compiler Component: ARM Compiler Tool: armcc [4d3621] """, "", 0) toolchain.version_check() assert len(notifier.messages) == 1
def test_filter_by_all_libraries(self): """ Assert something """ res = Resources(MockNotifier()) res._add_labels('TARGET', ['K64F', 'FRDM']) for name, loc in SRC_PATHS.items(): res.add_directory(loc, into_path=name) res.filter_by_libraries(res.get_file_refs(FileType.JSON)) assert ("main.cpp" in res.get_file_names(FileType.CPP_SRC))
def test_filter_by_all_libraries(self): """ Assert something """ res = Resources(MockNotifier(), collect_ignores=True) res._add_labels('TARGET', ['K64F', 'FRDM']) for name, loc in SRC_PATHS.items(): res.add_directory(loc, into_path=name) res.filter_by_libraries(res.get_file_refs(FileType.JSON)) assert ("main.cpp" in res.get_file_names(FileType.CPP_SRC)) lib_dirs = (dirname(name) or "." for name in res.get_file_names(FileType.JSON)) assert (not any(dir in res.ignored_dirs for dir in lib_dirs))
def test_detect_duplicates(self): """ Verify that detect_duplicates finds all of the duplicate object files in the scanned tree. """ notifier = MockNotifier() first = Resources(notifier) first._add_labels('TARGET', ['K64F']) for name, loc in SRC_PATHS.items(): first.add_directory(loc, into_path=name) notifier.messages = [] first.detect_duplicates() error_messages = "\n".join(m['message'] for m in notifier.messages if m['type'] == 'tool_error') assert (" eggs.o " in error_messages) first._add_labels('TARGET', ['FRDM']) first.detect_duplicates() error_messages = "\n".join(m['message'] for m in notifier.messages if m['type'] == 'tool_error') assert (" eggs.o " in error_messages) assert (" not-main.o " in error_messages) assert (" main.o " in error_messages)
def test_basic_scan(self): """ Verify that the ordering of Target info addition and directory addition does not matter, so long as all the Target info and all directories are added. """ first = Resources(MockNotifier()) first._add_labels('TARGET', ['K64F']) first._add_labels('TARGET', ['FRDM']) for name, loc in SRC_PATHS.items(): print(name, loc) first.add_directory(loc, into_path=name) assert ("main.cpp" in first.get_file_names(FileType.CPP_SRC))
def test_armc6_version_check(_run_cmd): set_targets_json_location() notifier = MockNotifier() print(TARGET_MAP["K64F"]) toolchain = TOOLCHAIN_CLASSES["ARMC6"](TARGET_MAP["K64F"], notify=notifier) print(toolchain) _run_cmd.return_value = (""" Product: ARM Compiler 6.11 Professional Component: ARM Compiler 6.11 Tool: armclang [5d3b4200] """, "", 0) toolchain.version_check() assert notifier.messages == []
def test_find_secure_image(): mock_notifier = MockNotifier() mock_resources = Resources(mock_notifier) ns_image_path = os.path.join('BUILD', 'TARGET_NS', 'app.bin') ns_test_path = os.path.join('BUILD', 'TARGET_NS', 'test.bin') config_s_image_name = 'target_config.bin' default_bin = os.path.join('prebuilt', config_s_image_name) test_bin = os.path.join('prebuilt', 'test.bin') with pytest.raises( Exception, match='ns_image_path and configured_s_image_path are mandatory'): find_secure_image(mock_notifier, mock_resources, None, None, FileType.BIN) find_secure_image(mock_notifier, mock_resources, ns_image_path, None, FileType.BIN) find_secure_image(mock_notifier, mock_resources, None, config_s_image_name, FileType.BIN) with pytest.raises(Exception, match='image_type must be of type BIN or HEX'): find_secure_image(mock_notifier, mock_resources, ns_image_path, config_s_image_name, None) find_secure_image(mock_notifier, mock_resources, ns_image_path, config_s_image_name, FileType.C_SRC) with pytest.raises(Exception, match='No image files found for this target'): find_secure_image(mock_notifier, mock_resources, ns_image_path, config_s_image_name, FileType.BIN) dummy_bin = os.path.join('path', 'to', 'dummy.bin') mock_resources.add_file_ref(FileType.BIN, dummy_bin, dummy_bin) with pytest.raises(Exception, match='Required secure image not found'): find_secure_image(mock_notifier, mock_resources, ns_image_path, config_s_image_name, FileType.BIN) mock_resources.add_file_ref(FileType.BIN, default_bin, default_bin) mock_resources.add_file_ref(FileType.BIN, test_bin, test_bin) secure_image = find_secure_image(mock_notifier, mock_resources, ns_image_path, config_s_image_name, FileType.BIN) assert secure_image == default_bin secure_image = find_secure_image(mock_notifier, mock_resources, ns_test_path, config_s_image_name, FileType.BIN) assert secure_image == test_bin
def test_add_target_info(self): """ Verify that the ordering of Target info addition and directory addition does not matter, so long as all the Target info and all directories are added. """ first = Resources(MockNotifier()) middle = Resources(MockNotifier()) last = Resources(MockNotifier()) first._add_labels('TARGET', ['K64F']) first._add_labels('TARGET', ['FRDM']) middle._add_labels('TARGET', ['FRDM']) for name, loc in SRC_PATHS.items(): first.add_directory(loc, into_path=name) middle.add_directory(loc, into_path=name) last.add_directory(loc, into_path=name) middle._add_labels('TARGET', ['K64F']) last._add_labels('TARGET', ['K64F']) last._add_labels('TARGET', ['FRDM']) for ftype in Resources.ALL_FILE_TYPES: assert (set(first.get_file_refs(ftype)) == set( middle.get_file_refs(ftype))) assert (set(last.get_file_refs(ftype)) == set( middle.get_file_refs(ftype)))
def test_filter_by_bm_lib(self): res = Resources(MockNotifier()) res._add_labels('TARGET', ['K64F', 'FRDM']) for name, loc in SRC_PATHS.items(): res.add_directory(loc, into_path=name) filter_by = [ ref for ref in res.get_file_refs(FileType.JSON) if join("platform", "bm", "mbed_lib.json") in ref.name ] res.filter_by_libraries(filter_by) assert ("main.cpp" not in res.get_file_names(FileType.CPP_SRC)) assert (join("mbed-os", "platform", "bm", "bm.cpp") in res.get_file_names(FileType.CPP_SRC)) assert (join("mbed-os", "TARGET_FRDM", "not-main.cpp") in res.get_file_names(FileType.CPP_SRC))
def test_detect_duplicates(filenames): c_sources = [os.path.join(name, "dupe.c") for name in filenames] s_sources = [os.path.join(name, "dupe.s") for name in filenames] cpp_sources = [os.path.join(name, "dupe.cpp") for name in filenames] notify = MockNotifier() res = Resources(notify) res.add_files_to_type(FileType.C_SRC, c_sources) res.add_files_to_type(FileType.ASM_SRC, s_sources) res.add_files_to_type(FileType.CPP_SRC, cpp_sources) assert res.detect_duplicates() == 1,\ "Not Enough duplicates found" notification = notify.messages[0] assert "dupe.o" in notification["message"] assert "dupe.s" in notification["message"] assert "dupe.c" in notification["message"] assert "dupe.cpp" in notification["message"]
def test_iar_version_check(_run_cmd): _run_cmd.return_value = (""" IAR ANSI C/C++ Compiler V7.80.1.28/LNX for ARM """, "", 0) notifier = MockNotifier() toolchain = TOOLCHAIN_CLASSES["IAR"](TARGET_MAP["K64F"], notify=notifier) toolchain.version_check() assert notifier.messages == [] _run_cmd.return_value = (""" IAR ANSI C/C++ Compiler V/LNX for ARM """, "", 0) toolchain.version_check() assert len(notifier.messages) == 1 _run_cmd.return_value = (""" IAR ANSI C/C++ Compiler V/8.80LNX for ARM """, "", 0) toolchain.version_check() assert len(notifier.messages) == 2
def test_detect_duplicates(filenames): c_sources = [os.path.join(name, "dupe.c") for name in filenames] s_sources = [os.path.join(name, "dupe.s") for name in filenames] cpp_sources = [os.path.join(name, "dupe.cpp") for name in filenames] notify = MockNotifier() toolchain = TOOLCHAIN_CLASSES["ARM"](TARGET_MAP["K64F"], notify=notify) res = Resources() res.c_sources = c_sources res.s_sources = s_sources res.cpp_sources = cpp_sources assert res.detect_duplicates(toolchain) == 1,\ "Not Enough duplicates found" notification = notify.messages[0] assert "dupe.o" in notification["message"] assert "dupe.s" in notification["message"] assert "dupe.c" in notification["message"] assert "dupe.cpp" in notification["message"]
def test_only_one_linker_script(self): """ Verify that when multiple linker scripts are added to a resource object, only the last one added is used. """ resources = Resources(MockNotifier()) linker_scripts = [ "first_linker_script.sct", "second_linker_script.sct" ] for linker_script in linker_scripts: resources.add_file_ref(FileType.LD_SCRIPT, linker_script, linker_script) assert (len(resources.get_file_refs(FileType.LD_SCRIPT)) == 1) assert (resources.get_file_refs( FileType.LD_SCRIPT)[-1].name == linker_scripts[-1]) assert (resources.get_file_refs( FileType.LD_SCRIPT)[-1].path == linker_scripts[-1])
def test_armc6_version_check(_run_cmd): set_targets_json_location() notifier = MockNotifier() toolchain = TOOLCHAIN_CLASSES["ARMC6"](TARGET_MAP["K64F"], notify=notifier) _run_cmd.return_value = (""" Product: ARM Compiler 6.11 Professional Component: ARM Compiler 6.11 Tool: armclang [5d3b4200] """, "", 0) toolchain.version_check() assert notifier.messages == [] assert not toolchain.is_mbed_studio_armc6 _run_cmd.return_value = (""" armclang: error: Failed to check out a license. The provided license does not enable these tools. Information about this error is available at: http://ds.arm.com/support/lic56/m5 General licensing information is available at: http://ds.arm.com/support/licensing/ If you need further help, provide this complete error report to your supplier or [email protected]. - ARMLMD_LICENSE_FILE: unset - LM_LICENSE_FILE: unset - ARM_TOOL_VARIANT: unset - ARM_PRODUCT_PATH: unset - Product location: C:\MbedStudio\tools\ac6\sw\mappings - Toolchain location: C:\MbedStudio\tools\ac6\bin - Selected tool variant: product - Checkout feature: mbed_armcompiler - Feature version: 5.0201810 - Flex error code: -5 Product: ARM Compiler 6.11 for Mbed Studio Component: ARM Compiler 6.11 Tool: armclang [5d3b3c00] """, "", 0) toolchain.version_check() assert notifier.messages == [] assert toolchain.is_mbed_studio_armc6
def test_gcc_version_check(_run_cmd): set_targets_json_location() _run_cmd.return_value = (""" arm-none-eabi-gcc (Arch Repository) 6.4.4 Copyright (C) 2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. """, "", 0) notifier = MockNotifier() toolchain = TOOLCHAIN_CLASSES["GCC_ARM"](TARGET_MAP["K64F"], notify=notifier) toolchain.version_check() assert len(notifier.messages) == 1 _run_cmd.return_value = (""" arm-none-eabi-gcc (GNU Tools for Arm Embedded Processors 9-2019-q4-major) 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599] Copyright (C) 2019 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. """, "", 0) toolchain.version_check() assert len(notifier.messages) == 1 _run_cmd.return_value = (""" arm-none-eabi-gcc (GNU Tools for Arm Embedded Processors 10-2020-q4-major) 10.2.1 20201025 (release) [ARM/arm-10-branch revision 377599] Copyright (C) 2020 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. """, "", 0) toolchain.version_check() assert len(notifier.messages) == 2 _run_cmd.return_value = (""" arm-none-eabi-gcc (Arch Repository) Copyright (C) 2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. """, "", 0) toolchain.version_check() assert len(notifier.messages) == 3
def test_filter_by_bm_lib(self): res = Resources(MockNotifier(), collect_ignores=True) res._add_labels('TARGET', ['K64F', 'FRDM']) for name, loc in SRC_PATHS.items(): res.add_directory(loc, into_path=name) libs = [ ref for ref in res.get_file_refs(FileType.JSON) if basename(ref.name) == MBED_LIB_FILENAME ] filter_by = [ ref for ref in libs if join("platform", "bm", "mbed_lib.json") in ref.name ] res.filter_by_libraries(filter_by) assert ("main.cpp" not in res.get_file_names(FileType.CPP_SRC)) assert (join("mbed-os", "platform", "bm", "bm.cpp") in res.get_file_names(FileType.CPP_SRC)) assert (join("mbed-os", "TARGET_FRDM", "not-main.cpp") in res.get_file_names(FileType.CPP_SRC)) inc_names = [dirname(name) or "." for name, _ in filter_by] assert (not any(d in res.ignored_dirs for d in inc_names)) excluded_libs = set(libs) - set(filter_by) exc_names = [dirname(name) or "." for name, _ in excluded_libs] assert (all(e in res.ignored_dirs for e in exc_names))