Skip to content

Tools Updates (Tests and build logs) #1928

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jun 14, 2016
Merged
4 changes: 0 additions & 4 deletions tools/build_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -383,8 +383,6 @@ def build_library(src_paths, build_path, target, toolchain_name,
if toolchain_output:
cur_result["output"] += toolchain_output

cur_result["output"] += str(e)

add_result_to_report(report, cur_result)

# Let Exception propagate
Expand Down Expand Up @@ -523,8 +521,6 @@ def build_lib(lib_id, target, toolchain_name, options=None, verbose=False, clean
if toolchain_output:
cur_result["output"] += toolchain_output

cur_result["output"] += str(e)

add_result_to_report(report, cur_result)

# Let Exception propagate
Expand Down
29 changes: 21 additions & 8 deletions tools/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import sys
import os
import json
import fnmatch

ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
sys.path.insert(0, ROOT)
Expand All @@ -29,7 +30,7 @@
from tools.options import get_default_options_parser
from tools.build_api import build_project, build_library
from tools.targets import TARGET_MAP
from tools.utils import mkdir
from tools.utils import mkdir, ToolException, NotSupportedException
from tools.test_exporters import ReportExporter, ResultExporterType

if __name__ == '__main__':
Expand Down Expand Up @@ -102,11 +103,13 @@
# Filter tests by name if specified
if options.names:
all_names = options.names.split(",")
all_names = [x.lower() for x in all_names]

all_tests_keys = all_tests.keys()
for name in all_names:
if name in all_tests_keys:
tests[name] = all_tests[name]
if any(fnmatch.fnmatch(testname, name) for testname in all_tests):
for testname, test in all_tests.items():
if fnmatch.fnmatch(testname, name):
tests[testname] = test
else:
print "[Warning] Test with name '%s' was not found in the available tests" % (name)
else:
Expand Down Expand Up @@ -134,7 +137,7 @@
build_report = {}
build_properties = {}

library_build_success = True
library_build_success = False
try:
# Build sources
build_library(base_source_paths, options.build_dir, target, options.tool,
Expand All @@ -147,11 +150,21 @@
macros=options.macros,
verbose=options.verbose,
archive=False)

library_build_success = True
except ToolException, e:
# ToolException output is handled by the build log
pass
except NotSupportedException, e:
# NotSupportedException is handled by the build log
pass
except Exception, e:
library_build_success = False
# Some other exception occurred, print the error message
print e

if not library_build_success:
print "Failed to build library"

if library_build_success:
else:
# Build all the tests
test_build_success, test_build = build_tests(tests, [options.build_dir], options.build_dir, target, options.tool,
options=options.options,
Expand Down
118 changes: 44 additions & 74 deletions tools/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1961,76 +1961,44 @@ def test_path_to_name(path):
name_parts.insert(0, tail)
head, tail = os.path.split(head)

return "-".join(name_parts)
return "-".join(name_parts).lower()

def find_tests(base_dir):
"""Given any directory, walk through the subdirectories and find all tests"""

def is_subdir(path, directory):
path = os.path.realpath(path)
directory = os.path.realpath(directory)
relative = os.path.relpath(path, directory)
return not (relative.startswith(os.pardir + os.sep) and relative.startswith(os.pardir))

def find_tests_in_tests_directory(directory):
def find_test_in_directory(directory, tests_path):
"""Given a 'TESTS' directory, return a dictionary of test names and test paths.
The formate of the dictionary is {"test-name": "./path/to/test"}"""
tests = {}

for d in os.listdir(directory):
# dir name host_tests is reserved for host python scripts.
if d != "host_tests":
# Loop on test case directories
for td in os.listdir(os.path.join(directory, d)):
# Add test case to the results if it is a directory and not "host_tests"
if td != "host_tests":
test_case_path = os.path.join(directory, d, td)
if os.path.isdir(test_case_path):
tests[test_path_to_name(test_case_path)] = test_case_path
test = None
if tests_path in directory:
head, test_case_directory = os.path.split(directory)
if test_case_directory != tests_path and test_case_directory != "host_tests":
head, test_group_directory = os.path.split(head)
if test_group_directory != tests_path and test_case_directory != "host_tests":
test = {
"name": test_path_to_name(directory),
"path": directory
}

return tests
return test

tests_path = 'TESTS'
tests = {}
dirs = scan_for_source_paths(base_dir)

# Determine if "base_dir" is already a "TESTS" directory
_, top_folder = os.path.split(base_dir)
for directory in dirs:
test = find_test_in_directory(directory, tests_path)
if test:
tests[test['name']] = test['path']

if top_folder == tests_path:
# Already pointing at a "TESTS" directory
return find_tests_in_tests_directory(base_dir)
else:
# Not pointing at a "TESTS" directory, so go find one!
tests = {}

dirs = scan_for_source_paths(base_dir)

test_and_sub_dirs = [x for x in dirs if tests_path in x]
test_dirs = []
for potential_test_dir in test_and_sub_dirs:
good_to_add = True
if test_dirs:
for test_dir in test_dirs:
if is_subdir(potential_test_dir, test_dir):
good_to_add = False
break

if good_to_add:
test_dirs.append(potential_test_dir)

# Only look at valid paths
for path in test_dirs:
# Get the tests inside of the "TESTS" directory
new_tests = find_tests_in_tests_directory(path)
if new_tests:
tests.update(new_tests)

return tests
return tests

def print_tests(tests, format="list"):
def print_tests(tests, format="list", sort=True):
"""Given a dictionary of tests (as returned from "find_tests"), print them
in the specified format"""
if format == "list":
for test_name, test_path in tests.iteritems():
for test_name in sorted(tests.keys()):
test_path = tests[test_name]
print "Test Case:"
print " Name: %s" % test_name
print " Path: %s" % test_path
Expand Down Expand Up @@ -2064,7 +2032,7 @@ def build_tests(tests, base_source_paths, build_path, target, toolchain_name,
for test_name, test_path in tests.iteritems():
test_build_path = os.path.join(build_path, test_path)
src_path = base_source_paths + [test_path]

bin_file = None
try:
bin_file = build_project(src_path, test_build_path, target, toolchain_name,
options=options,
Expand All @@ -2077,30 +2045,32 @@ def build_tests(tests, base_source_paths, build_path, target, toolchain_name,
verbose=verbose)

except Exception, e:
result = False

if continue_on_build_fail:
continue
else:
break
if not isinstance(e, NotSupportedException):
result = False

if continue_on_build_fail:
continue
else:
break

# If a clean build was carried out last time, disable it for the next build.
# Otherwise the previously built test will be deleted.
if clean:
clean = False

# Normalize the path
bin_file = os.path.normpath(bin_file)

test_build['tests'][test_name] = {
"binaries": [
{
"path": bin_file
}
]
}

print 'Image: %s'% bin_file
if bin_file:
bin_file = os.path.normpath(bin_file)

test_build['tests'][test_name] = {
"binaries": [
{
"path": bin_file
}
]
}

print 'Image: %s'% bin_file

test_builds = {}
test_builds["%s-%s" % (target.name, toolchain_name)] = test_build
Expand Down
19 changes: 11 additions & 8 deletions tools/test_exporters.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,15 +324,18 @@ def exporter_print(self, test_result_ext, print_log_for_failures=False):
for test_runner in test_runs:
#test_run = test_result_ext[target][toolchain][test][test_run_number][0]
test_run = test_runner[0]

if test_run["result"] == "FAIL":
failures.append(test_run)
elif test_run["result"] == "SKIP" or test_run["result"] == "NOT_SUPPORTED":
skips.append(test_run)
elif test_run["result"] == "OK":
successes.append(test_run)

if "result" in test_run:
if test_run["result"] == "FAIL":
failures.append(test_run)
elif test_run["result"] == "SKIP" or test_run["result"] == "NOT_SUPPORTED":
skips.append(test_run)
elif test_run["result"] == "OK":
successes.append(test_run)
else:
raise Exception("Unhandled result type: %s" % (test_run["result"]))
else:
raise Exception("Unhandled result type: %s" % (test_run["result"]))
raise Exception("'test_run' did not have a 'result' value")

if successes:
print "\n\nBuild successes:"
Expand Down
13 changes: 7 additions & 6 deletions tools/toolchains/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,9 @@ def __init__(self, target, options=None, notify=None, macros=None, silent=False,

self.mp_pool = None

if 'UVISOR_PRESENT=1' in self.macros:
if 'UVISOR' in self.target.features and 'UVISOR_SUPPORTED' in self.target.extra_labels:
self.target.core = re.sub(r"F$", '', self.target.core)

self.flags = deepcopy(self.DEFAULT_FLAGS)

def get_output(self):
Expand All @@ -253,9 +254,12 @@ def print_notify(self, event, silent=False):
"""
msg = None

if event['type'] in ['info', 'debug']:
if not self.VERBOSE and event['type'] == 'tool_error':
msg = event['message']


elif event['type'] in ['info', 'debug']:
msg = event['message']

elif event['type'] == 'cc':
event['severity'] = event['severity'].title()
event['file'] = basename(event['file'])
Expand Down Expand Up @@ -775,9 +779,6 @@ def link_program(self, r, tmp_path, name):
def default_cmd(self, command):
self.debug("Command: %s"% ' '.join(command))
_stdout, _stderr, _rc = run_cmd(command)
# Print all warning / erros from stderr to console output
for error_line in _stderr.splitlines():
print error_line

self.debug("Return: %s"% _rc)

Expand Down