Skip to content

Commit d4e5f2e

Browse files
committed
Adding test discovery logic to toolchains.
This allows toolchains to find test case directories when they are traversing the source tree. It must be done in the toolchians because they are aware of the target, toolchain, enabled features, config, and .mbedignore files.
1 parent 8d1d836 commit d4e5f2e

File tree

4 files changed

+59
-34
lines changed

4 files changed

+59
-34
lines changed

tools/test.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@
106106

107107
# Find all tests in the relevant paths
108108
for path in all_paths:
109-
all_tests.update(find_tests(path))
110-
109+
all_tests.update(find_tests(path, options.mcu, options.tool, options.options))
110+
111111
# Filter tests by name if specified
112112
if options.names:
113113
all_names = options.names

tools/test_api.py

Lines changed: 10 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,7 @@
5858
from tools.build_api import add_result_to_report
5959
from tools.build_api import scan_for_source_paths
6060
from tools.libraries import LIBRARIES, LIBRARY_MAP
61-
from tools.toolchains import TOOLCHAIN_BIN_PATH
62-
from tools.toolchains import TOOLCHAINS
61+
from tools.toolchains import TOOLCHAINS, TOOLCHAIN_BIN_PATH, TOOLCHAIN_CLASSES
6362
from tools.test_exporters import ReportExporter, ResultExporterType
6463
from tools.utils import argparse_filestring_type
6564
from tools.utils import argparse_uppercase_type
@@ -1975,6 +1974,7 @@ def get_default_test_options_parser():
19751974
help='Prints script version and exits')
19761975
return parser
19771976

1977+
19781978
def test_path_to_name(path):
19791979
"""Change all slashes in a path into hyphens
19801980
This creates a unique cross-platform test name based on the path
@@ -1987,33 +1987,19 @@ def test_path_to_name(path):
19871987

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

1990-
def find_tests(base_dir):
1990+
def find_tests(base_dir, target, toolchain, options):
19911991
"""Given any directory, walk through the subdirectories and find all tests"""
19921992

1993-
def find_test_in_directory(directory, tests_path):
1994-
"""Given a 'TESTS' directory, return a dictionary of test names and test paths.
1995-
The formate of the dictionary is {"test-name": "./path/to/test"}"""
1996-
test = None
1997-
if tests_path in directory:
1998-
head, test_case_directory = os.path.split(directory)
1999-
if test_case_directory != tests_path and test_case_directory != "host_tests":
2000-
head, test_group_directory = os.path.split(head)
2001-
if test_group_directory != tests_path and test_case_directory != "host_tests":
2002-
test = {
2003-
"name": test_path_to_name(directory),
2004-
"path": directory
2005-
}
2006-
2007-
return test
1993+
# If the 'target' argument is a string, convert it to a target instance
1994+
target = TARGET_MAP[target]
1995+
toolchain = TOOLCHAIN_CLASSES[toolchain](target)
1996+
resources = toolchain.scan_resources(base_dir)
20081997

2009-
tests_path = 'TESTS'
20101998
tests = {}
2011-
dirs = scan_for_source_paths(base_dir)
20121999

2013-
for directory in dirs:
2014-
test = find_test_in_directory(directory, tests_path)
2015-
if test:
2016-
tests[test['name']] = test['path']
2000+
for directory in resources.test_directories:
2001+
test_name = test_path_to_name(directory)
2002+
tests[test_name] = directory
20172003

20182004
return tests
20192005

tools/toolchains/__init__.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
from tools.config import Config
2929

3030
from multiprocessing import Pool, cpu_count
31-
from tools.utils import run_cmd, mkdir, rel_path, ToolException, NotSupportedException, split_path
31+
from tools.utils import run_cmd, mkdir, rel_path, ToolException, NotSupportedException, split_path, directory_in_path, is_test_directory
3232
from tools.settings import BUILD_OPTIONS, MBED_ORG_USER
3333
import tools.hooks as hooks
3434
from tools.memap import MemapParser
@@ -94,6 +94,10 @@ def __init__(self, base_path=None):
9494

9595
# Features
9696
self.features = {}
97+
98+
# Tests
99+
self.test_directories = []
100+
97101

98102
def __add__(self, resources):
99103
if resources is None:
@@ -496,7 +500,7 @@ def _add_dir(self, path, resources, base_path, exclude_paths=None):
496500
for d in copy(dirs):
497501
dir_path = join(root, d)
498502
# Add internal repo folders/files. This is needed for exporters
499-
if d == '.hg':
503+
if d == '.hg' and not directory_in_path('TESTS', relpath(root, path)):
500504
resources.repo_dirs.append(dir_path)
501505
resources.repo_files.extend(self.scan_repository(dir_path))
502506

@@ -506,10 +510,11 @@ def _add_dir(self, path, resources, base_path, exclude_paths=None):
506510
# Ignore toolchain that do not match the current TOOLCHAIN
507511
(d.startswith('TOOLCHAIN_') and d[10:] not in labels['TOOLCHAIN']) or
508512
# Ignore .mbedignore files
509-
self.is_ignored(join(dir_path,"")) or
510-
# Ignore TESTS dir
511-
(d == 'TESTS')):
513+
self.is_ignored(join(dir_path,""))):
512514
dirs.remove(d)
515+
elif is_test_directory(relpath(dir_path, path)):
516+
resources.test_directories.append(dir_path)
517+
dirs.remove(d)
513518
elif d.startswith('FEATURE_'):
514519
# Recursively scan features but ignore them in the current scan.
515520
# These are dynamically added by the config system if the conditions are matched
@@ -525,9 +530,10 @@ def _add_dir(self, path, resources, base_path, exclude_paths=None):
525530
# Add root to include paths
526531
resources.inc_dirs.append(root)
527532

528-
for file in files:
529-
file_path = join(root, file)
530-
self._add_file(file_path, resources, base_path)
533+
if not directory_in_path('TESTS', relpath(root, path)):
534+
for file in files:
535+
file_path = join(root, file)
536+
self._add_file(file_path, resources, base_path)
531537

532538
# A helper function for both scan_resources and _add_dir. _add_file adds one file
533539
# (*file_path*) to the resources object based on the file type.

tools/utils.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,22 @@ def find_cmd_abspath(cmd):
8383
return abspath
8484

8585

86+
def directory_in_path(directory, path):
87+
""" Returns True if `directory` is found within `path`.
88+
Ex. directory_in_path("dir", "/is/dir/in/here") returns True
89+
Ex. directory_in_path("dir", "/is/my_dir/in/here") returns False
90+
"""
91+
head, tail = split(path)
92+
93+
while tail:
94+
if tail == directory:
95+
return True
96+
else:
97+
head, tail = split(head)
98+
99+
return False
100+
101+
86102
def mkdir(path):
87103
if not exists(path):
88104
makedirs(path)
@@ -140,6 +156,23 @@ def split_path(path):
140156
return base, name, ext
141157

142158

159+
def is_test_directory(path):
160+
"""Given a path, return true if it is a test case directory.
161+
Directory must follow this pattern: TESTS/testgroup/testcase. This
162+
would return True."""
163+
tests_path = 'TESTS'
164+
if directory_in_path(tests_path, path):
165+
head, test_case_directory = split(path)
166+
if test_case_directory != tests_path and test_case_directory != "host_tests":
167+
head, test_group_directory = split(head)
168+
if test_group_directory != tests_path and test_case_directory != "host_tests":
169+
head, candidate_tests_path = split(head)
170+
if candidate_tests_path == tests_path:
171+
return True
172+
173+
return False
174+
175+
143176
def args_error(parser, message):
144177
print "\n\n%s\n\n" % message
145178
parser.print_help()

0 commit comments

Comments
 (0)