Skip to content

Commit 1618e60

Browse files
committed
Test discovery now uses build and toolchain logic
Previously, test discovery throught test.py used its own logic to find tests. This was mostly a subset of the rules used during the build process. It respected .mbedignore files, but it did not respect TARGET_, TOOLCHAIN_, and FEATURES_ directories. This change now uses the same logic used during building to respect these folders. Tests under these folders that are not being pulled in for the given target will be ignored.
1 parent a4fb649 commit 1618e60

File tree

4 files changed

+65
-92
lines changed

4 files changed

+65
-92
lines changed

tools/build_api.py

Lines changed: 0 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -970,63 +970,3 @@ def write_build_report(build_report, template_filename, filename):
970970

971971
with open(filename, 'w+') as f:
972972
f.write(template.render(failing_builds=build_report_failing, passing_builds=build_report_passing))
973-
974-
975-
def scan_for_source_paths(path, exclude_paths=None):
976-
ignorepatterns = []
977-
paths = []
978-
979-
def is_ignored(file_path):
980-
for pattern in ignorepatterns:
981-
if fnmatch.fnmatch(file_path, pattern):
982-
return True
983-
return False
984-
985-
986-
""" os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]])
987-
When topdown is True, the caller can modify the dirnames list in-place
988-
(perhaps using del or slice assignment), and walk() will only recurse into
989-
the subdirectories whose names remain in dirnames; this can be used to prune
990-
the search, impose a specific order of visiting, or even to inform walk()
991-
about directories the caller creates or renames before it resumes walk()
992-
again. Modifying dirnames when topdown is False is ineffective, because in
993-
bottom-up mode the directories in dirnames are generated before dirpath
994-
itself is generated.
995-
"""
996-
for root, dirs, files in walk(path, followlinks=True):
997-
# Remove ignored directories
998-
# Check if folder contains .mbedignore
999-
if ".mbedignore" in files :
1000-
with open (join(root,".mbedignore"), "r") as f:
1001-
lines=f.readlines()
1002-
lines = [l.strip() for l in lines] # Strip whitespaces
1003-
lines = [l for l in lines if l != ""] # Strip empty lines
1004-
lines = [l for l in lines if not re.match("^#",l)] # Strip comment lines
1005-
# Append root path to glob patterns
1006-
# and append patterns to ignorepatterns
1007-
ignorepatterns.extend([join(root,line.strip()) for line in lines])
1008-
1009-
for d in copy(dirs):
1010-
dir_path = join(root, d)
1011-
1012-
# Always ignore hidden directories
1013-
if d.startswith('.'):
1014-
dirs.remove(d)
1015-
1016-
# Remove dirs that already match the ignorepatterns
1017-
# to avoid travelling into them and to prevent them
1018-
# on appearing in include path.
1019-
if is_ignored(join(dir_path,"")):
1020-
dirs.remove(d)
1021-
1022-
if exclude_paths:
1023-
for exclude_path in exclude_paths:
1024-
rel_path = relpath(dir_path, exclude_path)
1025-
if not (rel_path.startswith('..')):
1026-
dirs.remove(d)
1027-
break
1028-
1029-
# Add root to include paths
1030-
paths.append(root)
1031-
1032-
return paths

tools/test.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,12 @@
105105
all_tests = {}
106106
tests = {}
107107

108+
target = options.mcu[0]
109+
toolchain = options.tool[0]
110+
108111
# Find all tests in the relevant paths
109112
for path in all_paths:
110-
all_tests.update(find_tests(path))
113+
all_tests.update(find_tests(path, target, toolchain, options.options))
111114

112115
# Filter tests by name if specified
113116
if options.names:
@@ -151,16 +154,13 @@
151154
if not base_source_paths:
152155
base_source_paths = ['.']
153156

154-
155-
target = options.mcu[0]
156-
157157
build_report = {}
158158
build_properties = {}
159159

160160
library_build_success = False
161161
try:
162162
# Build sources
163-
build_library(base_source_paths, options.build_dir, target, options.tool[0],
163+
build_library(base_source_paths, options.build_dir, target, toolchain,
164164
options=options.options,
165165
jobs=options.jobs,
166166
clean=options.clean,
@@ -187,7 +187,7 @@
187187
print "Failed to build library"
188188
else:
189189
# Build all the tests
190-
test_build_success, test_build = build_tests(tests, [options.build_dir], options.build_dir, target, options.tool[0],
190+
test_build_success, test_build = build_tests(tests, [options.build_dir], options.build_dir, target, toolchain,
191191
options=options.options,
192192
clean=options.clean,
193193
report=build_report,

tools/test_api.py

Lines changed: 41 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,11 @@
3131
from types import ListType
3232
from colorama import Fore, Back, Style
3333
from prettytable import PrettyTable
34+
from copy import copy
3435

3536
from time import sleep, time
3637
from Queue import Queue, Empty
37-
from os.path import join, exists, basename
38+
from os.path import join, exists, basename, relpath
3839
from threading import Thread, Lock
3940
from subprocess import Popen, PIPE
4041

@@ -56,7 +57,8 @@
5657
from tools.build_api import prep_properties
5758
from tools.build_api import create_result
5859
from tools.build_api import add_result_to_report
59-
from tools.build_api import scan_for_source_paths
60+
from tools.build_api import prepare_toolchain
61+
from tools.build_api import scan_resources
6062
from tools.libraries import LIBRARIES, LIBRARY_MAP
6163
from tools.toolchains import TOOLCHAIN_PATHS
6264
from tools.toolchains import TOOLCHAINS
@@ -65,6 +67,7 @@
6567
from tools.utils import argparse_uppercase_type
6668
from tools.utils import argparse_lowercase_type
6769
from tools.utils import argparse_many
70+
from tools.utils import get_path_depth
6871

6972
import tools.host_tests.host_tests_plugins as host_tests_plugins
7073

@@ -1987,33 +1990,46 @@ def test_path_to_name(path):
19871990

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

1990-
def find_tests(base_dir):
1991-
"""Given any directory, walk through the subdirectories and find all tests"""
1992-
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+
def find_tests(base_dir, target_name, toolchain_name, options=None):
1994+
""" Finds all tests in a directory recursively
1995+
base_dir: path to the directory to scan for tests (ex. 'path/to/project')
1996+
target_name: name of the target to use for scanning (ex. 'K64F')
1997+
toolchain_name: name of the toolchain to use for scanning (ex. 'GCC_ARM')
1998+
options: Compile options to pass to the toolchain (ex. ['debug-info'])
1999+
"""
20082000

2009-
tests_path = 'TESTS'
20102001
tests = {}
2011-
dirs = scan_for_source_paths(base_dir)
20122002

2003+
# Prepare the toolchain
2004+
toolchain = prepare_toolchain(base_dir, target_name, toolchain_name, options=options, silent=True)
2005+
2006+
# Scan the directory for paths to probe for 'TESTS' folders
2007+
base_resources = scan_resources(base_dir, toolchain)
2008+
2009+
dirs = base_resources.inc_dirs
20132010
for directory in dirs:
2014-
test = find_test_in_directory(directory, tests_path)
2015-
if test:
2016-
tests[test['name']] = test['path']
2011+
subdirs = os.listdir(directory)
2012+
2013+
# If the directory contains a subdirectory called 'TESTS', scan it for test cases
2014+
if 'TESTS' in subdirs:
2015+
walk_base_dir = join(directory, 'TESTS')
2016+
test_resources = toolchain.scan_resources(walk_base_dir, base_path=base_dir)
2017+
2018+
# Loop through all subdirectories
2019+
for d in test_resources.inc_dirs:
2020+
2021+
# If the test case folder is not called 'host_tests' and it is
2022+
# located two folders down from the main 'TESTS' folder (ex. TESTS/testgroup/testcase)
2023+
# then add it to the tests
2024+
path_depth = get_path_depth(relpath(d, walk_base_dir))
2025+
if path_depth == 2:
2026+
test_group_directory_path, test_case_directory = os.path.split(d)
2027+
test_group_directory = os.path.basename(test_group_directory_path)
2028+
2029+
# Check to make sure discoverd folder is not in a host test directory
2030+
if test_case_directory != 'host_tests' and test_group_directory != 'host_tests':
2031+
test_name = test_path_to_name(d)
2032+
tests[test_name] = d
20172033

20182034
return tests
20192035

tools/utils.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import math
2222
from os import listdir, remove, makedirs
2323
from shutil import copyfile
24-
from os.path import isdir, join, exists, split, relpath, splitext, abspath, commonprefix
24+
from os.path import isdir, join, exists, split, relpath, splitext, abspath, commonprefix, normpath
2525
from subprocess import Popen, PIPE, STDOUT, call
2626
import json
2727
from collections import OrderedDict
@@ -173,6 +173,23 @@ def split_path(path):
173173
return base, name, ext
174174

175175

176+
def get_path_depth(path):
177+
""" Given a path, return the number of directory levels present.
178+
This roughly translates to the number of path separators (os.sep) + 1.
179+
Ex. Given "path/to/dir", this would return 3
180+
Special cases: "." and "/" return 0
181+
"""
182+
normalized_path = normpath(path)
183+
path_depth = 0
184+
head, tail = split(normalized_path)
185+
186+
while(tail and tail != '.'):
187+
path_depth += 1
188+
head, tail = split(head)
189+
190+
return path_depth
191+
192+
176193
def args_error(parser, message):
177194
print "\n\n%s\n\n" % message
178195
parser.print_help()

0 commit comments

Comments
 (0)