2016-09-27 23:36:30 +00:00
|
|
|
"""Tests for the toolchain sub-system"""
|
2016-07-14 19:11:30 +00:00
|
|
|
import sys
|
|
|
|
import os
|
2016-09-27 22:40:18 +00:00
|
|
|
from string import printable
|
|
|
|
from copy import deepcopy
|
2016-10-03 20:15:08 +00:00
|
|
|
from mock import MagicMock, patch
|
2017-03-07 17:41:56 +00:00
|
|
|
from hypothesis import given, settings
|
|
|
|
from hypothesis.strategies import text, lists, fixed_dictionaries, booleans
|
2016-07-14 19:11:30 +00:00
|
|
|
|
2016-09-27 23:36:30 +00:00
|
|
|
ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..",
|
|
|
|
".."))
|
2016-07-14 19:11:30 +00:00
|
|
|
sys.path.insert(0, ROOT)
|
|
|
|
|
2016-09-30 20:09:18 +00:00
|
|
|
from tools.toolchains import TOOLCHAIN_CLASSES, LEGACY_TOOLCHAIN_NAMES,\
|
2017-09-22 15:51:43 +00:00
|
|
|
Resources, TOOLCHAIN_PATHS, mbedToolchain
|
2016-07-14 19:11:30 +00:00
|
|
|
from tools.targets import TARGET_MAP
|
2018-05-01 14:10:59 +00:00
|
|
|
from tools.notifier.mock import MockNotifier
|
2016-07-14 19:11:30 +00:00
|
|
|
|
2018-05-31 21:32:31 +00:00
|
|
|
ALPHABET = [char for char in printable if char not in [u'.', u'/', u'\\']]
|
2016-09-27 22:40:18 +00:00
|
|
|
|
2018-06-26 14:15:01 +00:00
|
|
|
@patch('tools.toolchains.arm.run_cmd')
|
|
|
|
def test_arm_version_check(_run_cmd):
|
|
|
|
_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: ARM Compiler
|
|
|
|
Component: ARM Compiler
|
|
|
|
Tool: armcc [4d3621]
|
|
|
|
""", "", 0)
|
|
|
|
toolchain.version_check()
|
|
|
|
assert len(notifier.messages) == 1
|
|
|
|
|
2016-09-27 22:40:18 +00:00
|
|
|
@given(fixed_dictionaries({
|
|
|
|
'common': lists(text()),
|
|
|
|
'c': lists(text()),
|
|
|
|
'cxx': lists(text()),
|
|
|
|
'asm': lists(text()),
|
|
|
|
'ld': lists(text())}),
|
2016-09-27 23:36:30 +00:00
|
|
|
lists(text(min_size=1, alphabet=ALPHABET), min_size=1))
|
2016-09-27 22:40:18 +00:00
|
|
|
def test_toolchain_profile_c(profile, source_file):
|
2016-09-27 23:36:30 +00:00
|
|
|
"""Test that the appropriate profile parameters are passed to the
|
|
|
|
C compiler"""
|
2016-09-27 22:40:18 +00:00
|
|
|
filename = deepcopy(source_file)
|
|
|
|
filename[-1] += ".c"
|
|
|
|
to_compile = os.path.join(*filename)
|
2016-10-03 20:15:08 +00:00
|
|
|
with patch('os.mkdir') as _mkdir:
|
|
|
|
for _, tc_class in TOOLCHAIN_CLASSES.items():
|
2018-05-01 14:10:59 +00:00
|
|
|
toolchain = tc_class(TARGET_MAP["K64F"], build_profile=profile,
|
|
|
|
notify=MockNotifier())
|
2016-10-03 20:15:08 +00:00
|
|
|
toolchain.inc_md5 = ""
|
|
|
|
toolchain.build_dir = ""
|
2017-06-05 20:45:51 +00:00
|
|
|
toolchain.config = MagicMock(app_config_location=None)
|
2017-09-22 15:51:43 +00:00
|
|
|
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)
|
2016-10-03 20:15:08 +00:00
|
|
|
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), \
|
2017-09-22 15:51:43 +00:00
|
|
|
"Toolchain %s did not propagate arg %s" % (toolchain.name,
|
2016-10-03 20:15:08 +00:00
|
|
|
parameter)
|
2016-09-27 22:40:18 +00:00
|
|
|
|
|
|
|
@given(fixed_dictionaries({
|
|
|
|
'common': lists(text()),
|
|
|
|
'c': lists(text()),
|
|
|
|
'cxx': lists(text()),
|
|
|
|
'asm': lists(text()),
|
|
|
|
'ld': lists(text())}),
|
2016-09-27 23:36:30 +00:00
|
|
|
lists(text(min_size=1, alphabet=ALPHABET), min_size=1))
|
2016-09-27 22:40:18 +00:00
|
|
|
def test_toolchain_profile_cpp(profile, source_file):
|
2016-09-27 23:36:30 +00:00
|
|
|
"""Test that the appropriate profile parameters are passed to the
|
|
|
|
C++ compiler"""
|
2016-09-27 22:40:18 +00:00
|
|
|
filename = deepcopy(source_file)
|
|
|
|
filename[-1] += ".cpp"
|
|
|
|
to_compile = os.path.join(*filename)
|
2016-10-03 20:15:08 +00:00
|
|
|
with patch('os.mkdir') as _mkdir:
|
|
|
|
for _, tc_class in TOOLCHAIN_CLASSES.items():
|
2018-05-01 14:10:59 +00:00
|
|
|
toolchain = tc_class(TARGET_MAP["K64F"], build_profile=profile,
|
|
|
|
notify=MockNotifier())
|
2016-10-03 20:15:08 +00:00
|
|
|
toolchain.inc_md5 = ""
|
|
|
|
toolchain.build_dir = ""
|
2017-06-05 20:45:51 +00:00
|
|
|
toolchain.config = MagicMock(app_config_location=None)
|
2017-09-22 15:51:43 +00:00
|
|
|
for parameter in profile['cxx'] + profile['common']:
|
|
|
|
assert any(parameter in cmd for cmd in toolchain.cppc), \
|
|
|
|
"Toolchain %s did not propagate arg %s" % (toolchain.name,
|
|
|
|
parameter)
|
2016-10-03 20:15:08 +00:00
|
|
|
compile_command = toolchain.compile_command(to_compile,
|
|
|
|
to_compile + ".o", [])
|
|
|
|
for parameter in profile['cxx'] + profile['common']:
|
|
|
|
assert any(parameter in cmd for cmd in compile_command), \
|
2017-09-22 15:51:43 +00:00
|
|
|
"Toolchain %s did not propagate arg %s" % (toolchain.name,
|
2016-10-03 20:15:08 +00:00
|
|
|
parameter)
|
2016-09-27 22:40:18 +00:00
|
|
|
|
|
|
|
@given(fixed_dictionaries({
|
|
|
|
'common': lists(text()),
|
|
|
|
'c': lists(text()),
|
|
|
|
'cxx': lists(text()),
|
|
|
|
'asm': lists(text()),
|
|
|
|
'ld': lists(text())}),
|
2016-09-27 23:36:30 +00:00
|
|
|
lists(text(min_size=1, alphabet=ALPHABET), min_size=1))
|
2016-09-27 22:40:18 +00:00
|
|
|
def test_toolchain_profile_asm(profile, source_file):
|
2016-09-27 23:36:30 +00:00
|
|
|
"""Test that the appropriate profile parameters are passed to the
|
|
|
|
Assembler"""
|
2016-09-27 22:40:18 +00:00
|
|
|
filename = deepcopy(source_file)
|
|
|
|
filename[-1] += ".s"
|
|
|
|
to_compile = os.path.join(*filename)
|
2016-10-03 20:15:08 +00:00
|
|
|
with patch('os.mkdir') as _mkdir:
|
|
|
|
for _, tc_class in TOOLCHAIN_CLASSES.items():
|
2018-05-01 14:10:59 +00:00
|
|
|
toolchain = tc_class(TARGET_MAP["K64F"], build_profile=profile,
|
|
|
|
notify=MockNotifier)
|
2016-10-03 20:15:08 +00:00
|
|
|
toolchain.inc_md5 = ""
|
|
|
|
toolchain.build_dir = ""
|
2017-09-22 15:51:43 +00:00
|
|
|
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)
|
2016-10-03 20:15:08 +00:00
|
|
|
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), \
|
2017-09-22 15:51:43 +00:00
|
|
|
"Toolchain %s did not propagate arg %s" % (toolchain.name,
|
|
|
|
parameter)
|
|
|
|
|
|
|
|
for name, Class in TOOLCHAIN_CLASSES.items():
|
2018-05-01 14:10:59 +00:00
|
|
|
CLS = Class(TARGET_MAP["K64F"], notify=MockNotifier())
|
2017-09-22 15:51:43 +00:00
|
|
|
assert name == CLS.name or name == LEGACY_TOOLCHAIN_NAMES[CLS.name]
|
|
|
|
|
|
|
|
@given(fixed_dictionaries({
|
|
|
|
'common': lists(text()),
|
|
|
|
'c': lists(text()),
|
|
|
|
'cxx': lists(text()),
|
|
|
|
'asm': lists(text()),
|
|
|
|
'ld': lists(text(min_size=1))}),
|
|
|
|
lists(text(min_size=1, alphabet=ALPHABET), min_size=1))
|
|
|
|
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():
|
2018-05-01 14:10:59 +00:00
|
|
|
toolchain = tc_class(TARGET_MAP["K64F"], build_profile=profile,
|
|
|
|
notify=MockNotifier())
|
2017-09-22 15:51:43 +00:00
|
|
|
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)
|
2016-09-27 22:40:18 +00:00
|
|
|
|
2016-09-30 20:09:18 +00:00
|
|
|
for name, Class in TOOLCHAIN_CLASSES.items():
|
2018-05-01 14:10:59 +00:00
|
|
|
CLS = Class(TARGET_MAP["K64F"], notify=MockNotifier())
|
2016-09-30 20:09:18 +00:00
|
|
|
assert name == CLS.name or name == LEGACY_TOOLCHAIN_NAMES[CLS.name]
|
|
|
|
|
|
|
|
|
|
|
|
@given(lists(text(alphabet=ALPHABET, min_size=1), min_size=1))
|
|
|
|
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]
|
2018-05-01 14:10:59 +00:00
|
|
|
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"
|
2016-09-30 20:09:18 +00:00
|
|
|
|
2018-05-01 14:10:59 +00:00
|
|
|
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"]
|
2017-03-07 17:41:56 +00:00
|
|
|
|
2018-05-31 21:32:31 +00:00
|
|
|
@given(text(alphabet=ALPHABET + [os.sep], min_size=1))
|
2017-03-07 17:41:56 +00:00
|
|
|
@given(booleans())
|
|
|
|
@given(booleans())
|
|
|
|
@settings(max_examples=20)
|
|
|
|
def test_path_specified_gcc(gcc_loc, exists_at_loc, exists_in_path):
|
|
|
|
with patch('tools.toolchains.gcc.exists') as _exists:
|
|
|
|
with patch('tools.toolchains.gcc.find_executable') as _find:
|
|
|
|
_exists.return_value = exists_at_loc
|
|
|
|
_find.return_value = exists_in_path
|
|
|
|
TOOLCHAIN_PATHS['GCC_ARM'] = gcc_loc
|
|
|
|
toolchain_class = TOOLCHAIN_CLASSES["GCC_ARM"]
|
|
|
|
found_p = toolchain_class.check_executable()
|
|
|
|
assert found_p == (exists_at_loc or exists_in_path)
|
|
|
|
if exists_at_loc:
|
|
|
|
assert TOOLCHAIN_PATHS['GCC_ARM'] == gcc_loc
|
|
|
|
elif exists_in_path:
|
|
|
|
assert TOOLCHAIN_PATHS['GCC_ARM'] == ''
|