mbed-os
Dependents: cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more
tools/test/toolchains/api_test.py@0:b74591d5ab33, 2017-12-11 (annotated)
- Committer:
- be_bryan
- Date:
- Mon Dec 11 17:54:04 2017 +0000
- Revision:
- 0:b74591d5ab33
motor ++
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
be_bryan | 0:b74591d5ab33 | 1 | """Tests for the toolchain sub-system""" |
be_bryan | 0:b74591d5ab33 | 2 | import sys |
be_bryan | 0:b74591d5ab33 | 3 | import os |
be_bryan | 0:b74591d5ab33 | 4 | from string import printable |
be_bryan | 0:b74591d5ab33 | 5 | from copy import deepcopy |
be_bryan | 0:b74591d5ab33 | 6 | from mock import MagicMock, patch |
be_bryan | 0:b74591d5ab33 | 7 | from hypothesis import given, settings |
be_bryan | 0:b74591d5ab33 | 8 | from hypothesis.strategies import text, lists, fixed_dictionaries, booleans |
be_bryan | 0:b74591d5ab33 | 9 | |
be_bryan | 0:b74591d5ab33 | 10 | ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", |
be_bryan | 0:b74591d5ab33 | 11 | "..")) |
be_bryan | 0:b74591d5ab33 | 12 | sys.path.insert(0, ROOT) |
be_bryan | 0:b74591d5ab33 | 13 | |
be_bryan | 0:b74591d5ab33 | 14 | from tools.toolchains import TOOLCHAIN_CLASSES, LEGACY_TOOLCHAIN_NAMES,\ |
be_bryan | 0:b74591d5ab33 | 15 | Resources, TOOLCHAIN_PATHS, mbedToolchain |
be_bryan | 0:b74591d5ab33 | 16 | from tools.targets import TARGET_MAP |
be_bryan | 0:b74591d5ab33 | 17 | |
be_bryan | 0:b74591d5ab33 | 18 | def test_instantiation(): |
be_bryan | 0:b74591d5ab33 | 19 | """Test that all exported toolchain may be instantiated""" |
be_bryan | 0:b74591d5ab33 | 20 | for name, tc_class in TOOLCHAIN_CLASSES.items(): |
be_bryan | 0:b74591d5ab33 | 21 | cls = tc_class(TARGET_MAP["K64F"]) |
be_bryan | 0:b74591d5ab33 | 22 | assert name == cls.name or\ |
be_bryan | 0:b74591d5ab33 | 23 | name == LEGACY_TOOLCHAIN_NAMES[cls.name] |
be_bryan | 0:b74591d5ab33 | 24 | |
be_bryan | 0:b74591d5ab33 | 25 | ALPHABET = [char for char in printable if char not in [u'.', u'/']] |
be_bryan | 0:b74591d5ab33 | 26 | |
be_bryan | 0:b74591d5ab33 | 27 | @given(fixed_dictionaries({ |
be_bryan | 0:b74591d5ab33 | 28 | 'common': lists(text()), |
be_bryan | 0:b74591d5ab33 | 29 | 'c': lists(text()), |
be_bryan | 0:b74591d5ab33 | 30 | 'cxx': lists(text()), |
be_bryan | 0:b74591d5ab33 | 31 | 'asm': lists(text()), |
be_bryan | 0:b74591d5ab33 | 32 | 'ld': lists(text())}), |
be_bryan | 0:b74591d5ab33 | 33 | lists(text(min_size=1, alphabet=ALPHABET), min_size=1)) |
be_bryan | 0:b74591d5ab33 | 34 | def test_toolchain_profile_c(profile, source_file): |
be_bryan | 0:b74591d5ab33 | 35 | """Test that the appropriate profile parameters are passed to the |
be_bryan | 0:b74591d5ab33 | 36 | C compiler""" |
be_bryan | 0:b74591d5ab33 | 37 | filename = deepcopy(source_file) |
be_bryan | 0:b74591d5ab33 | 38 | filename[-1] += ".c" |
be_bryan | 0:b74591d5ab33 | 39 | to_compile = os.path.join(*filename) |
be_bryan | 0:b74591d5ab33 | 40 | with patch('os.mkdir') as _mkdir: |
be_bryan | 0:b74591d5ab33 | 41 | for _, tc_class in TOOLCHAIN_CLASSES.items(): |
be_bryan | 0:b74591d5ab33 | 42 | toolchain = tc_class(TARGET_MAP["K64F"], build_profile=profile) |
be_bryan | 0:b74591d5ab33 | 43 | toolchain.inc_md5 = "" |
be_bryan | 0:b74591d5ab33 | 44 | toolchain.build_dir = "" |
be_bryan | 0:b74591d5ab33 | 45 | toolchain.config = MagicMock(app_config_location=None) |
be_bryan | 0:b74591d5ab33 | 46 | for parameter in profile['c'] + profile['common']: |
be_bryan | 0:b74591d5ab33 | 47 | assert any(parameter in cmd for cmd in toolchain.cc), \ |
be_bryan | 0:b74591d5ab33 | 48 | "Toolchain %s did not propagate arg %s" % (toolchain.name, |
be_bryan | 0:b74591d5ab33 | 49 | parameter) |
be_bryan | 0:b74591d5ab33 | 50 | compile_command = toolchain.compile_command(to_compile, |
be_bryan | 0:b74591d5ab33 | 51 | to_compile + ".o", []) |
be_bryan | 0:b74591d5ab33 | 52 | for parameter in profile['c'] + profile['common']: |
be_bryan | 0:b74591d5ab33 | 53 | assert any(parameter in cmd for cmd in compile_command), \ |
be_bryan | 0:b74591d5ab33 | 54 | "Toolchain %s did not propagate arg %s" % (toolchain.name, |
be_bryan | 0:b74591d5ab33 | 55 | parameter) |
be_bryan | 0:b74591d5ab33 | 56 | |
be_bryan | 0:b74591d5ab33 | 57 | @given(fixed_dictionaries({ |
be_bryan | 0:b74591d5ab33 | 58 | 'common': lists(text()), |
be_bryan | 0:b74591d5ab33 | 59 | 'c': lists(text()), |
be_bryan | 0:b74591d5ab33 | 60 | 'cxx': lists(text()), |
be_bryan | 0:b74591d5ab33 | 61 | 'asm': lists(text()), |
be_bryan | 0:b74591d5ab33 | 62 | 'ld': lists(text())}), |
be_bryan | 0:b74591d5ab33 | 63 | lists(text(min_size=1, alphabet=ALPHABET), min_size=1)) |
be_bryan | 0:b74591d5ab33 | 64 | def test_toolchain_profile_cpp(profile, source_file): |
be_bryan | 0:b74591d5ab33 | 65 | """Test that the appropriate profile parameters are passed to the |
be_bryan | 0:b74591d5ab33 | 66 | C++ compiler""" |
be_bryan | 0:b74591d5ab33 | 67 | filename = deepcopy(source_file) |
be_bryan | 0:b74591d5ab33 | 68 | filename[-1] += ".cpp" |
be_bryan | 0:b74591d5ab33 | 69 | to_compile = os.path.join(*filename) |
be_bryan | 0:b74591d5ab33 | 70 | with patch('os.mkdir') as _mkdir: |
be_bryan | 0:b74591d5ab33 | 71 | for _, tc_class in TOOLCHAIN_CLASSES.items(): |
be_bryan | 0:b74591d5ab33 | 72 | toolchain = tc_class(TARGET_MAP["K64F"], build_profile=profile) |
be_bryan | 0:b74591d5ab33 | 73 | toolchain.inc_md5 = "" |
be_bryan | 0:b74591d5ab33 | 74 | toolchain.build_dir = "" |
be_bryan | 0:b74591d5ab33 | 75 | toolchain.config = MagicMock(app_config_location=None) |
be_bryan | 0:b74591d5ab33 | 76 | for parameter in profile['cxx'] + profile['common']: |
be_bryan | 0:b74591d5ab33 | 77 | assert any(parameter in cmd for cmd in toolchain.cppc), \ |
be_bryan | 0:b74591d5ab33 | 78 | "Toolchain %s did not propagate arg %s" % (toolchain.name, |
be_bryan | 0:b74591d5ab33 | 79 | parameter) |
be_bryan | 0:b74591d5ab33 | 80 | compile_command = toolchain.compile_command(to_compile, |
be_bryan | 0:b74591d5ab33 | 81 | to_compile + ".o", []) |
be_bryan | 0:b74591d5ab33 | 82 | for parameter in profile['cxx'] + profile['common']: |
be_bryan | 0:b74591d5ab33 | 83 | assert any(parameter in cmd for cmd in compile_command), \ |
be_bryan | 0:b74591d5ab33 | 84 | "Toolchain %s did not propagate arg %s" % (toolchain.name, |
be_bryan | 0:b74591d5ab33 | 85 | parameter) |
be_bryan | 0:b74591d5ab33 | 86 | |
be_bryan | 0:b74591d5ab33 | 87 | @given(fixed_dictionaries({ |
be_bryan | 0:b74591d5ab33 | 88 | 'common': lists(text()), |
be_bryan | 0:b74591d5ab33 | 89 | 'c': lists(text()), |
be_bryan | 0:b74591d5ab33 | 90 | 'cxx': lists(text()), |
be_bryan | 0:b74591d5ab33 | 91 | 'asm': lists(text()), |
be_bryan | 0:b74591d5ab33 | 92 | 'ld': lists(text())}), |
be_bryan | 0:b74591d5ab33 | 93 | lists(text(min_size=1, alphabet=ALPHABET), min_size=1)) |
be_bryan | 0:b74591d5ab33 | 94 | def test_toolchain_profile_asm(profile, source_file): |
be_bryan | 0:b74591d5ab33 | 95 | """Test that the appropriate profile parameters are passed to the |
be_bryan | 0:b74591d5ab33 | 96 | Assembler""" |
be_bryan | 0:b74591d5ab33 | 97 | filename = deepcopy(source_file) |
be_bryan | 0:b74591d5ab33 | 98 | filename[-1] += ".s" |
be_bryan | 0:b74591d5ab33 | 99 | to_compile = os.path.join(*filename) |
be_bryan | 0:b74591d5ab33 | 100 | with patch('os.mkdir') as _mkdir: |
be_bryan | 0:b74591d5ab33 | 101 | for _, tc_class in TOOLCHAIN_CLASSES.items(): |
be_bryan | 0:b74591d5ab33 | 102 | toolchain = tc_class(TARGET_MAP["K64F"], build_profile=profile) |
be_bryan | 0:b74591d5ab33 | 103 | toolchain.inc_md5 = "" |
be_bryan | 0:b74591d5ab33 | 104 | toolchain.build_dir = "" |
be_bryan | 0:b74591d5ab33 | 105 | for parameter in profile['asm']: |
be_bryan | 0:b74591d5ab33 | 106 | assert any(parameter in cmd for cmd in toolchain.asm), \ |
be_bryan | 0:b74591d5ab33 | 107 | "Toolchain %s did not propagate arg %s" % (toolchain.name, |
be_bryan | 0:b74591d5ab33 | 108 | parameter) |
be_bryan | 0:b74591d5ab33 | 109 | compile_command = toolchain.compile_command(to_compile, |
be_bryan | 0:b74591d5ab33 | 110 | to_compile + ".o", []) |
be_bryan | 0:b74591d5ab33 | 111 | if not compile_command: |
be_bryan | 0:b74591d5ab33 | 112 | assert compile_command, to_compile |
be_bryan | 0:b74591d5ab33 | 113 | for parameter in profile['asm']: |
be_bryan | 0:b74591d5ab33 | 114 | assert any(parameter in cmd for cmd in compile_command), \ |
be_bryan | 0:b74591d5ab33 | 115 | "Toolchain %s did not propagate arg %s" % (toolchain.name, |
be_bryan | 0:b74591d5ab33 | 116 | parameter) |
be_bryan | 0:b74591d5ab33 | 117 | |
be_bryan | 0:b74591d5ab33 | 118 | for name, Class in TOOLCHAIN_CLASSES.items(): |
be_bryan | 0:b74591d5ab33 | 119 | CLS = Class(TARGET_MAP["K64F"]) |
be_bryan | 0:b74591d5ab33 | 120 | assert name == CLS.name or name == LEGACY_TOOLCHAIN_NAMES[CLS.name] |
be_bryan | 0:b74591d5ab33 | 121 | |
be_bryan | 0:b74591d5ab33 | 122 | @given(fixed_dictionaries({ |
be_bryan | 0:b74591d5ab33 | 123 | 'common': lists(text()), |
be_bryan | 0:b74591d5ab33 | 124 | 'c': lists(text()), |
be_bryan | 0:b74591d5ab33 | 125 | 'cxx': lists(text()), |
be_bryan | 0:b74591d5ab33 | 126 | 'asm': lists(text()), |
be_bryan | 0:b74591d5ab33 | 127 | 'ld': lists(text(min_size=1))}), |
be_bryan | 0:b74591d5ab33 | 128 | lists(text(min_size=1, alphabet=ALPHABET), min_size=1)) |
be_bryan | 0:b74591d5ab33 | 129 | def test_toolchain_profile_ld(profile, source_file): |
be_bryan | 0:b74591d5ab33 | 130 | """Test that the appropriate profile parameters are passed to the |
be_bryan | 0:b74591d5ab33 | 131 | Linker""" |
be_bryan | 0:b74591d5ab33 | 132 | filename = deepcopy(source_file) |
be_bryan | 0:b74591d5ab33 | 133 | filename[-1] += ".o" |
be_bryan | 0:b74591d5ab33 | 134 | to_compile = os.path.join(*filename) |
be_bryan | 0:b74591d5ab33 | 135 | with patch('os.mkdir') as _mkdir,\ |
be_bryan | 0:b74591d5ab33 | 136 | patch('tools.toolchains.mbedToolchain.default_cmd') as _dflt_cmd: |
be_bryan | 0:b74591d5ab33 | 137 | for _, tc_class in TOOLCHAIN_CLASSES.items(): |
be_bryan | 0:b74591d5ab33 | 138 | toolchain = tc_class(TARGET_MAP["K64F"], build_profile=profile) |
be_bryan | 0:b74591d5ab33 | 139 | toolchain.RESPONSE_FILES = False |
be_bryan | 0:b74591d5ab33 | 140 | toolchain.inc_md5 = "" |
be_bryan | 0:b74591d5ab33 | 141 | toolchain.build_dir = "" |
be_bryan | 0:b74591d5ab33 | 142 | for parameter in profile['ld']: |
be_bryan | 0:b74591d5ab33 | 143 | assert any(parameter in cmd for cmd in toolchain.ld), \ |
be_bryan | 0:b74591d5ab33 | 144 | "Toolchain %s did not propagate arg %s" % (toolchain.name, |
be_bryan | 0:b74591d5ab33 | 145 | parameter) |
be_bryan | 0:b74591d5ab33 | 146 | toolchain.link(to_compile + ".elf", [to_compile], [], [], None) |
be_bryan | 0:b74591d5ab33 | 147 | compile_cmd = _dflt_cmd.call_args_list |
be_bryan | 0:b74591d5ab33 | 148 | if not compile_cmd: |
be_bryan | 0:b74591d5ab33 | 149 | assert compile_cmd, to_compile |
be_bryan | 0:b74591d5ab33 | 150 | for parameter in profile['ld']: |
be_bryan | 0:b74591d5ab33 | 151 | assert any(parameter in cmd[0][0] for cmd in compile_cmd), \ |
be_bryan | 0:b74591d5ab33 | 152 | "Toolchain %s did not propagate arg %s" % (toolchain.name, |
be_bryan | 0:b74591d5ab33 | 153 | parameter) |
be_bryan | 0:b74591d5ab33 | 154 | |
be_bryan | 0:b74591d5ab33 | 155 | for name, Class in TOOLCHAIN_CLASSES.items(): |
be_bryan | 0:b74591d5ab33 | 156 | CLS = Class(TARGET_MAP["K64F"]) |
be_bryan | 0:b74591d5ab33 | 157 | assert name == CLS.name or name == LEGACY_TOOLCHAIN_NAMES[CLS.name] |
be_bryan | 0:b74591d5ab33 | 158 | |
be_bryan | 0:b74591d5ab33 | 159 | |
be_bryan | 0:b74591d5ab33 | 160 | @given(lists(text(alphabet=ALPHABET, min_size=1), min_size=1)) |
be_bryan | 0:b74591d5ab33 | 161 | def test_detect_duplicates(filenames): |
be_bryan | 0:b74591d5ab33 | 162 | c_sources = [os.path.join(name, "dupe.c") for name in filenames] |
be_bryan | 0:b74591d5ab33 | 163 | s_sources = [os.path.join(name, "dupe.s") for name in filenames] |
be_bryan | 0:b74591d5ab33 | 164 | cpp_sources = [os.path.join(name, "dupe.cpp") for name in filenames] |
be_bryan | 0:b74591d5ab33 | 165 | with MagicMock() as notify: |
be_bryan | 0:b74591d5ab33 | 166 | toolchain = TOOLCHAIN_CLASSES["ARM"](TARGET_MAP["K64F"], notify=notify) |
be_bryan | 0:b74591d5ab33 | 167 | res = Resources() |
be_bryan | 0:b74591d5ab33 | 168 | res.c_sources = c_sources |
be_bryan | 0:b74591d5ab33 | 169 | res.s_sources = s_sources |
be_bryan | 0:b74591d5ab33 | 170 | res.cpp_sources = cpp_sources |
be_bryan | 0:b74591d5ab33 | 171 | assert res.detect_duplicates(toolchain) == 1,\ |
be_bryan | 0:b74591d5ab33 | 172 | "Not Enough duplicates found" |
be_bryan | 0:b74591d5ab33 | 173 | |
be_bryan | 0:b74591d5ab33 | 174 | _, (notification, _), _ = notify.mock_calls[1] |
be_bryan | 0:b74591d5ab33 | 175 | assert "dupe.o" in notification["message"] |
be_bryan | 0:b74591d5ab33 | 176 | assert "dupe.s" in notification["message"] |
be_bryan | 0:b74591d5ab33 | 177 | assert "dupe.c" in notification["message"] |
be_bryan | 0:b74591d5ab33 | 178 | assert "dupe.cpp" in notification["message"] |
be_bryan | 0:b74591d5ab33 | 179 | |
be_bryan | 0:b74591d5ab33 | 180 | @given(text(alphabet=ALPHABET + ["/"], min_size=1)) |
be_bryan | 0:b74591d5ab33 | 181 | @given(booleans()) |
be_bryan | 0:b74591d5ab33 | 182 | @given(booleans()) |
be_bryan | 0:b74591d5ab33 | 183 | @settings(max_examples=20) |
be_bryan | 0:b74591d5ab33 | 184 | def test_path_specified_gcc(gcc_loc, exists_at_loc, exists_in_path): |
be_bryan | 0:b74591d5ab33 | 185 | with patch('tools.toolchains.gcc.exists') as _exists: |
be_bryan | 0:b74591d5ab33 | 186 | with patch('tools.toolchains.gcc.find_executable') as _find: |
be_bryan | 0:b74591d5ab33 | 187 | _exists.return_value = exists_at_loc |
be_bryan | 0:b74591d5ab33 | 188 | _find.return_value = exists_in_path |
be_bryan | 0:b74591d5ab33 | 189 | TOOLCHAIN_PATHS['GCC_ARM'] = gcc_loc |
be_bryan | 0:b74591d5ab33 | 190 | toolchain_class = TOOLCHAIN_CLASSES["GCC_ARM"] |
be_bryan | 0:b74591d5ab33 | 191 | found_p = toolchain_class.check_executable() |
be_bryan | 0:b74591d5ab33 | 192 | assert found_p == (exists_at_loc or exists_in_path) |
be_bryan | 0:b74591d5ab33 | 193 | if exists_at_loc: |
be_bryan | 0:b74591d5ab33 | 194 | assert TOOLCHAIN_PATHS['GCC_ARM'] == gcc_loc |
be_bryan | 0:b74591d5ab33 | 195 | elif exists_in_path: |
be_bryan | 0:b74591d5ab33 | 196 | assert TOOLCHAIN_PATHS['GCC_ARM'] == '' |