takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers api_test.py Source File

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'] == ''