Skip to content

Commit fc4f1e2

Browse files
committed
Merge pull request #71 from bridadan/test-build
Building tests and test specs
2 parents 7aefc06 + 1d28050 commit fc4f1e2

File tree

3 files changed

+164
-17
lines changed

3 files changed

+164
-17
lines changed

tools/test.py

Lines changed: 99 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,42 +21,126 @@
2121
import sys
2222
import os
2323
import json
24-
from optparse import OptionParser
2524

2625
ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
2726
sys.path.insert(0, ROOT)
2827

29-
from tools.test_api import test_path_to_name, find_tests, print_tests
28+
from tools.test_api import test_path_to_name, find_tests, print_tests, build_tests, test_spec_from_test_build
29+
from tools.options import get_default_options_parser
30+
from tools.build_api import build_project
31+
from tools.targets import TARGET_MAP
32+
from tools.utils import mkdir
3033

3134
if __name__ == '__main__':
3235
try:
3336
# Parse Options
34-
parser = OptionParser()
37+
parser = get_default_options_parser()
38+
39+
parser.add_option("-j", "--jobs",
40+
type="int",
41+
dest="jobs",
42+
default=1,
43+
help="Number of concurrent jobs (default 1). Use 0 for auto based on host machine's number of CPUs")
44+
45+
parser.add_option("--source", dest="source_dir",
46+
default=None, help="The source (input) directory (for sources other than tests). Defaults to current directory.", action="append")
47+
48+
parser.add_option("--build", dest="build_dir",
49+
default=None, help="The build (output) directory")
3550

3651
parser.add_option("-l", "--list", action="store_true", dest="list",
3752
default=False, help="List (recursively) available tests in order and exit")
3853

3954
parser.add_option("-p", "--paths", dest="paths",
4055
default=None, help="Limit the tests to those within the specified comma separated list of paths")
4156

57+
format_choices = ["list", "json"]
58+
format_default_choice = "list"
59+
format_help = "Change the format in which tests are listed. Choices include: %s. Default: %s" % (", ".join(format_choices), format_default_choice)
4260
parser.add_option("-f", "--format", type="choice", dest="format",
43-
choices=["list", "json"], default="list", help="List available tests in order and exit")
61+
choices=format_choices, default=format_default_choice, help=format_help)
62+
63+
parser.add_option("-n", "--names", dest="names",
64+
default=None, help="Limit the tests to a comma separated list of names")
65+
66+
parser.add_option("--test-spec", dest="test_spec",
67+
default=None, help="Destination path for a test spec file that can be used by the Greentea automated test tool")
68+
69+
parser.add_option("-v", "--verbose",
70+
action="store_true",
71+
dest="verbose",
72+
default=False,
73+
help="Verbose diagnostic output")
4474

4575
(options, args) = parser.parse_args()
4676

47-
# Print available tests in order and exit
48-
if options.list is True:
49-
tests = {}
50-
51-
if options.paths:
52-
all_paths = options.paths.split(",")
53-
for path in all_paths:
54-
tests.update(find_tests(path))
55-
else:
56-
tests = find_tests('.')
77+
# Filter tests by path if specified
78+
if options.paths:
79+
all_paths = options.paths.split(",")
80+
else:
81+
all_paths = ["."]
82+
83+
all_tests = {}
84+
tests = {}
85+
86+
# Find all tests in the relevant paths
87+
for path in all_paths:
88+
all_tests.update(find_tests(path))
89+
90+
# Filter tests by name if specified
91+
if options.names:
92+
all_names = options.names.split(",")
5793

94+
all_tests_keys = all_tests.keys()
95+
for name in all_names:
96+
if name in all_tests_keys:
97+
tests[name] = all_tests[name]
98+
else:
99+
print "[Warning] Test with name '%s' was not found in the available tests" % (name)
100+
else:
101+
tests = all_tests
102+
103+
if options.list:
104+
# Print available tests in order and exit
58105
print_tests(tests, options.format)
59-
sys.exit()
106+
else:
107+
# Build all tests
108+
if not options.build_dir:
109+
print "[ERROR] You must specify a build path"
110+
sys.exit(1)
111+
112+
base_source_paths = options.source_dir
113+
114+
# Default base source path is the current directory
115+
if not base_source_paths:
116+
base_source_paths = ['.']
117+
118+
target = TARGET_MAP[options.mcu]
119+
120+
# Build all the tests
121+
test_build = build_tests(tests, base_source_paths, options.build_dir, target, options.tool,
122+
options=options.options,
123+
clean=options.clean,
124+
jobs=options.jobs)
125+
126+
# If a path to a test spec is provided, write it to a file
127+
if options.test_spec:
128+
test_spec_data = test_spec_from_test_build(test_build)
129+
130+
# Create the target dir for the test spec if necessary
131+
# mkdir will not create the dir if it already exists
132+
test_spec_dir = os.path.dirname(options.test_spec)
133+
if test_spec_dir:
134+
mkdir(test_spec_dir)
135+
136+
try:
137+
with open(options.test_spec, 'w') as f:
138+
f.write(json.dumps(test_spec_data, indent=2))
139+
except IOError, e:
140+
print "[ERROR] Error writing test spec to file"
141+
print e
142+
143+
sys.exit()
60144

61145
except KeyboardInterrupt, e:
62146
print "\n[CTRL+c] exit"

tools/test_api.py

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2023,4 +2023,62 @@ def print_tests(tests, format="list"):
20232023
print json.dumps(tests, indent=2)
20242024
else:
20252025
print "Unknown format '%s'" % format
2026-
sys.exit(1)
2026+
sys.exit(1)
2027+
2028+
def build_tests(tests, base_source_paths, build_path, target, toolchain_name,
2029+
options=None, clean=False, notify=None, verbose=False, jobs=1,
2030+
silent=False, report=None, properties=None):
2031+
"""Given the data structure from 'find_tests' and the typical build parameters,
2032+
build all the tests and return a test build data structure"""
2033+
2034+
test_build = {
2035+
"platform": target.name,
2036+
"toolchain": toolchain_name,
2037+
"base_path": build_path,
2038+
"baud_rate": 9600,
2039+
"binary_type": "bootable",
2040+
"tests": {}
2041+
}
2042+
2043+
for test_name, test_path in tests.iteritems():
2044+
src_path = base_source_paths + [test_path]
2045+
artifact_name = os.path.join(test_path, test_name)
2046+
bin_file = build_project(src_path, build_path, target, toolchain_name,
2047+
options=options,
2048+
jobs=jobs,
2049+
clean=clean,
2050+
name=artifact_name,
2051+
report=report,
2052+
properties=properties,
2053+
verbose=verbose)
2054+
2055+
# If a clean build was carried out last time, disable it for the next build.
2056+
# Otherwise the previously built test will be deleted.
2057+
if clean:
2058+
clean = False
2059+
2060+
# Normalize the path
2061+
bin_file = os.path.normpath(bin_file)
2062+
2063+
test_build['tests'][test_name] = {
2064+
"binaries": [
2065+
{
2066+
"path": bin_file
2067+
}
2068+
]
2069+
}
2070+
2071+
print 'Image: %s'% bin_file
2072+
2073+
test_builds = {}
2074+
test_builds["%s-%s" % (target.name, toolchain_name)] = test_build
2075+
2076+
2077+
return test_builds
2078+
2079+
2080+
def test_spec_from_test_build(test_builds):
2081+
return {
2082+
"builds": test_builds
2083+
}
2084+

tools/toolchains/__init__.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -685,7 +685,12 @@ def link_program(self, r, tmp_path, name):
685685
if self.target.OUTPUT_NAMING == "8.3":
686686
name = name[0:8]
687687
ext = ext[0:3]
688-
688+
689+
# Create destination directory
690+
head, tail = split(name)
691+
new_path = join(tmp_path, head)
692+
mkdir(new_path)
693+
689694
filename = name+'.'+ext
690695
elf = join(tmp_path, name + '.elf')
691696
bin = join(tmp_path, filename)

0 commit comments

Comments
 (0)