Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-sdk-tools by
test.py@32:8ea194f6145b, 2017-01-04 (annotated)
- Committer:
- The Other Jimmy
- Date:
- Wed Jan 04 11:58:24 2017 -0600
- Revision:
- 32:8ea194f6145b
- Parent:
- 30:f12ce67666d0
Update tools to follow mbed-os tools release 5.3.1
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
screamer | 0:66f3b5499f7f | 1 | #! /usr/bin/env python2 |
screamer | 0:66f3b5499f7f | 2 | """ |
screamer | 0:66f3b5499f7f | 3 | mbed SDK |
screamer | 0:66f3b5499f7f | 4 | Copyright (c) 2011-2013 ARM Limited |
screamer | 0:66f3b5499f7f | 5 | |
screamer | 0:66f3b5499f7f | 6 | Licensed under the Apache License, Version 2.0 (the "License"); |
screamer | 0:66f3b5499f7f | 7 | you may not use this file except in compliance with the License. |
screamer | 0:66f3b5499f7f | 8 | You may obtain a copy of the License at |
screamer | 0:66f3b5499f7f | 9 | |
screamer | 0:66f3b5499f7f | 10 | http://www.apache.org/licenses/LICENSE-2.0 |
screamer | 0:66f3b5499f7f | 11 | |
screamer | 0:66f3b5499f7f | 12 | Unless required by applicable law or agreed to in writing, software |
screamer | 0:66f3b5499f7f | 13 | distributed under the License is distributed on an "AS IS" BASIS, |
screamer | 0:66f3b5499f7f | 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
screamer | 0:66f3b5499f7f | 15 | See the License for the specific language governing permissions and |
screamer | 0:66f3b5499f7f | 16 | limitations under the License. |
screamer | 0:66f3b5499f7f | 17 | |
screamer | 0:66f3b5499f7f | 18 | |
screamer | 0:66f3b5499f7f | 19 | TEST BUILD & RUN |
screamer | 0:66f3b5499f7f | 20 | """ |
screamer | 0:66f3b5499f7f | 21 | import sys |
screamer | 0:66f3b5499f7f | 22 | import os |
screamer | 0:66f3b5499f7f | 23 | import json |
screamer | 13:ab47a20b66f0 | 24 | import fnmatch |
screamer | 0:66f3b5499f7f | 25 | |
screamer | 0:66f3b5499f7f | 26 | ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) |
screamer | 0:66f3b5499f7f | 27 | sys.path.insert(0, ROOT) |
screamer | 0:66f3b5499f7f | 28 | |
The Other Jimmy |
32:8ea194f6145b | 29 | from tools.config import ConfigException |
screamer | 13:ab47a20b66f0 | 30 | from tools.test_api import test_path_to_name, find_tests, print_tests, build_tests, test_spec_from_test_builds |
The Other Jimmy |
32:8ea194f6145b | 31 | from tools.options import get_default_options_parser, extract_profile |
screamer | 0:66f3b5499f7f | 32 | from tools.build_api import build_project, build_library |
screamer | 29:1210849dba19 | 33 | from tools.build_api import print_build_memory_usage |
screamer | 0:66f3b5499f7f | 34 | from tools.targets import TARGET_MAP |
screamer | 24:25bff2709c20 | 35 | from tools.utils import mkdir, ToolException, NotSupportedException, args_error |
screamer | 13:ab47a20b66f0 | 36 | from tools.test_exporters import ReportExporter, ResultExporterType |
screamer | 22:9e85236d8716 | 37 | from utils import argparse_filestring_type, argparse_lowercase_type, argparse_many |
screamer | 24:25bff2709c20 | 38 | from utils import argparse_dir_not_parent |
The Other Jimmy |
32:8ea194f6145b | 39 | from tools.toolchains import mbedToolchain, TOOLCHAIN_PATHS, TOOLCHAIN_CLASSES |
screamer | 22:9e85236d8716 | 40 | from tools.settings import CLI_COLOR_MAP |
screamer | 0:66f3b5499f7f | 41 | |
screamer | 0:66f3b5499f7f | 42 | if __name__ == '__main__': |
screamer | 0:66f3b5499f7f | 43 | try: |
screamer | 0:66f3b5499f7f | 44 | # Parse Options |
The Other Jimmy |
32:8ea194f6145b | 45 | parser = get_default_options_parser(add_app_config=True) |
screamer | 0:66f3b5499f7f | 46 | |
screamer | 22:9e85236d8716 | 47 | parser.add_argument("-D", |
screamer | 13:ab47a20b66f0 | 48 | action="append", |
screamer | 13:ab47a20b66f0 | 49 | dest="macros", |
screamer | 13:ab47a20b66f0 | 50 | help="Add a macro definition") |
screamer | 22:9e85236d8716 | 51 | |
screamer | 22:9e85236d8716 | 52 | parser.add_argument("-j", "--jobs", |
screamer | 22:9e85236d8716 | 53 | type=int, |
screamer | 0:66f3b5499f7f | 54 | dest="jobs", |
screamer | 13:ab47a20b66f0 | 55 | default=0, |
screamer | 13:ab47a20b66f0 | 56 | help="Number of concurrent jobs. Default: 0/auto (based on host machine's number of CPUs)") |
screamer | 0:66f3b5499f7f | 57 | |
screamer | 22:9e85236d8716 | 58 | parser.add_argument("--source", dest="source_dir", |
screamer | 22:9e85236d8716 | 59 | type=argparse_filestring_type, |
screamer | 22:9e85236d8716 | 60 | default=None, help="The source (input) directory (for sources other than tests). Defaults to current directory.", action="append") |
screamer | 0:66f3b5499f7f | 61 | |
screamer | 24:25bff2709c20 | 62 | parser.add_argument("--build", dest="build_dir", type=argparse_dir_not_parent(ROOT), |
screamer | 0:66f3b5499f7f | 63 | default=None, help="The build (output) directory") |
screamer | 0:66f3b5499f7f | 64 | |
screamer | 22:9e85236d8716 | 65 | parser.add_argument("-l", "--list", action="store_true", dest="list", |
screamer | 0:66f3b5499f7f | 66 | default=False, help="List (recursively) available tests in order and exit") |
screamer | 0:66f3b5499f7f | 67 | |
screamer | 22:9e85236d8716 | 68 | parser.add_argument("-p", "--paths", dest="paths", |
screamer | 22:9e85236d8716 | 69 | type=argparse_many(argparse_filestring_type), |
screamer | 0:66f3b5499f7f | 70 | default=None, help="Limit the tests to those within the specified comma separated list of paths") |
screamer | 22:9e85236d8716 | 71 | |
screamer | 0:66f3b5499f7f | 72 | format_choices = ["list", "json"] |
screamer | 0:66f3b5499f7f | 73 | format_default_choice = "list" |
screamer | 0:66f3b5499f7f | 74 | format_help = "Change the format in which tests are listed. Choices include: %s. Default: %s" % (", ".join(format_choices), format_default_choice) |
screamer | 22:9e85236d8716 | 75 | parser.add_argument("-f", "--format", dest="format", |
screamer | 22:9e85236d8716 | 76 | type=argparse_lowercase_type(format_choices, "format"), |
screamer | 22:9e85236d8716 | 77 | default=format_default_choice, help=format_help) |
screamer | 0:66f3b5499f7f | 78 | |
screamer | 22:9e85236d8716 | 79 | parser.add_argument("--continue-on-build-fail", action="store_true", dest="continue_on_build_fail", |
screamer | 13:ab47a20b66f0 | 80 | default=None, help="Continue trying to build all tests if a build failure occurs") |
screamer | 13:ab47a20b66f0 | 81 | |
screamer | 22:9e85236d8716 | 82 | #TODO validate the names instead of just passing through str |
screamer | 22:9e85236d8716 | 83 | parser.add_argument("-n", "--names", dest="names", type=argparse_many(str), |
screamer | 0:66f3b5499f7f | 84 | default=None, help="Limit the tests to a comma separated list of names") |
screamer | 0:66f3b5499f7f | 85 | |
screamer | 22:9e85236d8716 | 86 | parser.add_argument("--test-spec", dest="test_spec", |
screamer | 0:66f3b5499f7f | 87 | default=None, help="Destination path for a test spec file that can be used by the Greentea automated test tool") |
screamer | 0:66f3b5499f7f | 88 | |
screamer | 22:9e85236d8716 | 89 | parser.add_argument("--build-report-junit", dest="build_report_junit", |
screamer | 13:ab47a20b66f0 | 90 | default=None, help="Destination path for a build report in the JUnit xml format") |
screamer | 13:ab47a20b66f0 | 91 | |
screamer | 22:9e85236d8716 | 92 | parser.add_argument("-v", "--verbose", |
screamer | 0:66f3b5499f7f | 93 | action="store_true", |
screamer | 0:66f3b5499f7f | 94 | dest="verbose", |
screamer | 0:66f3b5499f7f | 95 | default=False, |
screamer | 0:66f3b5499f7f | 96 | help="Verbose diagnostic output") |
screamer | 0:66f3b5499f7f | 97 | |
screamer | 22:9e85236d8716 | 98 | options = parser.parse_args() |
screamer | 0:66f3b5499f7f | 99 | |
screamer | 22:9e85236d8716 | 100 | # Filter tests by path if specified |
screamer | 0:66f3b5499f7f | 101 | if options.paths: |
screamer | 22:9e85236d8716 | 102 | all_paths = options.paths |
screamer | 0:66f3b5499f7f | 103 | else: |
screamer | 0:66f3b5499f7f | 104 | all_paths = ["."] |
screamer | 22:9e85236d8716 | 105 | |
screamer | 0:66f3b5499f7f | 106 | all_tests = {} |
screamer | 0:66f3b5499f7f | 107 | tests = {} |
screamer | 22:9e85236d8716 | 108 | |
screamer | 24:25bff2709c20 | 109 | # Target |
screamer | 24:25bff2709c20 | 110 | if options.mcu is None : |
The Other Jimmy |
32:8ea194f6145b | 111 | args_error(parser, "argument -m/--mcu is required") |
screamer | 24:25bff2709c20 | 112 | mcu = options.mcu[0] |
screamer | 24:25bff2709c20 | 113 | |
screamer | 24:25bff2709c20 | 114 | # Toolchain |
screamer | 24:25bff2709c20 | 115 | if options.tool is None: |
The Other Jimmy |
32:8ea194f6145b | 116 | args_error(parser, "argument -t/--tool is required") |
screamer | 24:25bff2709c20 | 117 | toolchain = options.tool[0] |
screamer | 24:25bff2709c20 | 118 | |
The Other Jimmy |
32:8ea194f6145b | 119 | if not TOOLCHAIN_CLASSES[toolchain].check_executable(): |
The Other Jimmy |
32:8ea194f6145b | 120 | search_path = TOOLCHAIN_PATHS[toolchain] or "No path set" |
The Other Jimmy |
32:8ea194f6145b | 121 | args_error(parser, "Could not find executable for %s.\n" |
The Other Jimmy |
32:8ea194f6145b | 122 | "Currently set search path: %s" |
The Other Jimmy |
32:8ea194f6145b | 123 | % (toolchain, search_path)) |
The Other Jimmy |
32:8ea194f6145b | 124 | |
screamer | 0:66f3b5499f7f | 125 | # Find all tests in the relevant paths |
screamer | 0:66f3b5499f7f | 126 | for path in all_paths: |
The Other Jimmy |
32:8ea194f6145b | 127 | all_tests.update(find_tests(path, mcu, toolchain, |
The Other Jimmy |
32:8ea194f6145b | 128 | app_config=options.app_config)) |
screamer | 22:9e85236d8716 | 129 | |
screamer | 0:66f3b5499f7f | 130 | # Filter tests by name if specified |
screamer | 0:66f3b5499f7f | 131 | if options.names: |
screamer | 22:9e85236d8716 | 132 | all_names = options.names |
screamer | 13:ab47a20b66f0 | 133 | all_names = [x.lower() for x in all_names] |
screamer | 22:9e85236d8716 | 134 | |
screamer | 0:66f3b5499f7f | 135 | for name in all_names: |
screamer | 13:ab47a20b66f0 | 136 | if any(fnmatch.fnmatch(testname, name) for testname in all_tests): |
screamer | 13:ab47a20b66f0 | 137 | for testname, test in all_tests.items(): |
screamer | 13:ab47a20b66f0 | 138 | if fnmatch.fnmatch(testname, name): |
screamer | 13:ab47a20b66f0 | 139 | tests[testname] = test |
screamer | 0:66f3b5499f7f | 140 | else: |
screamer | 0:66f3b5499f7f | 141 | print "[Warning] Test with name '%s' was not found in the available tests" % (name) |
screamer | 0:66f3b5499f7f | 142 | else: |
screamer | 0:66f3b5499f7f | 143 | tests = all_tests |
screamer | 0:66f3b5499f7f | 144 | |
screamer | 22:9e85236d8716 | 145 | if options.color: |
screamer | 22:9e85236d8716 | 146 | # This import happens late to prevent initializing colorization when we don't need it |
screamer | 22:9e85236d8716 | 147 | import colorize |
screamer | 22:9e85236d8716 | 148 | if options.verbose: |
screamer | 22:9e85236d8716 | 149 | notify = mbedToolchain.print_notify_verbose |
screamer | 22:9e85236d8716 | 150 | else: |
screamer | 22:9e85236d8716 | 151 | notify = mbedToolchain.print_notify |
screamer | 22:9e85236d8716 | 152 | notify = colorize.print_in_color_notifier(CLI_COLOR_MAP, notify) |
screamer | 22:9e85236d8716 | 153 | else: |
screamer | 22:9e85236d8716 | 154 | notify = None |
screamer | 22:9e85236d8716 | 155 | |
screamer | 0:66f3b5499f7f | 156 | if options.list: |
screamer | 0:66f3b5499f7f | 157 | # Print available tests in order and exit |
screamer | 0:66f3b5499f7f | 158 | print_tests(tests, options.format) |
screamer | 13:ab47a20b66f0 | 159 | sys.exit(0) |
screamer | 0:66f3b5499f7f | 160 | else: |
screamer | 0:66f3b5499f7f | 161 | # Build all tests |
screamer | 0:66f3b5499f7f | 162 | if not options.build_dir: |
The Other Jimmy |
32:8ea194f6145b | 163 | args_error(parser, "argument --build is required") |
screamer | 22:9e85236d8716 | 164 | |
screamer | 0:66f3b5499f7f | 165 | base_source_paths = options.source_dir |
screamer | 22:9e85236d8716 | 166 | |
screamer | 0:66f3b5499f7f | 167 | # Default base source path is the current directory |
screamer | 0:66f3b5499f7f | 168 | if not base_source_paths: |
screamer | 0:66f3b5499f7f | 169 | base_source_paths = ['.'] |
screamer | 0:66f3b5499f7f | 170 | |
screamer | 13:ab47a20b66f0 | 171 | build_report = {} |
screamer | 13:ab47a20b66f0 | 172 | build_properties = {} |
screamer | 13:ab47a20b66f0 | 173 | |
screamer | 13:ab47a20b66f0 | 174 | library_build_success = False |
The Other Jimmy |
32:8ea194f6145b | 175 | profile = extract_profile(parser, options, toolchain) |
screamer | 13:ab47a20b66f0 | 176 | try: |
screamer | 13:ab47a20b66f0 | 177 | # Build sources |
screamer | 24:25bff2709c20 | 178 | build_library(base_source_paths, options.build_dir, mcu, toolchain, |
screamer | 13:ab47a20b66f0 | 179 | jobs=options.jobs, |
screamer | 13:ab47a20b66f0 | 180 | clean=options.clean, |
screamer | 13:ab47a20b66f0 | 181 | report=build_report, |
screamer | 13:ab47a20b66f0 | 182 | properties=build_properties, |
screamer | 13:ab47a20b66f0 | 183 | name="mbed-build", |
screamer | 13:ab47a20b66f0 | 184 | macros=options.macros, |
screamer | 13:ab47a20b66f0 | 185 | verbose=options.verbose, |
screamer | 22:9e85236d8716 | 186 | notify=notify, |
The Other Jimmy |
32:8ea194f6145b | 187 | archive=False, |
The Other Jimmy |
32:8ea194f6145b | 188 | app_config=options.app_config, |
The Other Jimmy |
32:8ea194f6145b | 189 | build_profile=profile) |
screamer | 22:9e85236d8716 | 190 | |
screamer | 13:ab47a20b66f0 | 191 | library_build_success = True |
screamer | 13:ab47a20b66f0 | 192 | except ToolException, e: |
screamer | 13:ab47a20b66f0 | 193 | # ToolException output is handled by the build log |
screamer | 13:ab47a20b66f0 | 194 | pass |
screamer | 13:ab47a20b66f0 | 195 | except NotSupportedException, e: |
screamer | 13:ab47a20b66f0 | 196 | # NotSupportedException is handled by the build log |
screamer | 13:ab47a20b66f0 | 197 | pass |
screamer | 13:ab47a20b66f0 | 198 | except Exception, e: |
screamer | 13:ab47a20b66f0 | 199 | # Some other exception occurred, print the error message |
screamer | 13:ab47a20b66f0 | 200 | print e |
screamer | 22:9e85236d8716 | 201 | |
screamer | 13:ab47a20b66f0 | 202 | if not library_build_success: |
screamer | 13:ab47a20b66f0 | 203 | print "Failed to build library" |
screamer | 13:ab47a20b66f0 | 204 | else: |
screamer | 13:ab47a20b66f0 | 205 | # Build all the tests |
The Other Jimmy |
32:8ea194f6145b | 206 | |
screamer | 24:25bff2709c20 | 207 | test_build_success, test_build = build_tests(tests, [options.build_dir], options.build_dir, mcu, toolchain, |
screamer | 13:ab47a20b66f0 | 208 | clean=options.clean, |
screamer | 13:ab47a20b66f0 | 209 | report=build_report, |
screamer | 13:ab47a20b66f0 | 210 | properties=build_properties, |
screamer | 13:ab47a20b66f0 | 211 | macros=options.macros, |
screamer | 13:ab47a20b66f0 | 212 | verbose=options.verbose, |
screamer | 22:9e85236d8716 | 213 | notify=notify, |
screamer | 13:ab47a20b66f0 | 214 | jobs=options.jobs, |
The Other Jimmy |
32:8ea194f6145b | 215 | continue_on_build_fail=options.continue_on_build_fail, |
The Other Jimmy |
32:8ea194f6145b | 216 | app_config=options.app_config, |
The Other Jimmy |
32:8ea194f6145b | 217 | build_profile=profile) |
screamer | 22:9e85236d8716 | 218 | |
screamer | 13:ab47a20b66f0 | 219 | # If a path to a test spec is provided, write it to a file |
screamer | 13:ab47a20b66f0 | 220 | if options.test_spec: |
screamer | 13:ab47a20b66f0 | 221 | test_spec_data = test_spec_from_test_builds(test_build) |
screamer | 22:9e85236d8716 | 222 | |
screamer | 13:ab47a20b66f0 | 223 | # Create the target dir for the test spec if necessary |
screamer | 13:ab47a20b66f0 | 224 | # mkdir will not create the dir if it already exists |
screamer | 13:ab47a20b66f0 | 225 | test_spec_dir = os.path.dirname(options.test_spec) |
screamer | 13:ab47a20b66f0 | 226 | if test_spec_dir: |
screamer | 13:ab47a20b66f0 | 227 | mkdir(test_spec_dir) |
screamer | 22:9e85236d8716 | 228 | |
screamer | 13:ab47a20b66f0 | 229 | try: |
screamer | 13:ab47a20b66f0 | 230 | with open(options.test_spec, 'w') as f: |
screamer | 13:ab47a20b66f0 | 231 | f.write(json.dumps(test_spec_data, indent=2)) |
screamer | 13:ab47a20b66f0 | 232 | except IOError, e: |
screamer | 13:ab47a20b66f0 | 233 | print "[ERROR] Error writing test spec to file" |
screamer | 13:ab47a20b66f0 | 234 | print e |
screamer | 22:9e85236d8716 | 235 | |
screamer | 13:ab47a20b66f0 | 236 | # If a path to a JUnit build report spec is provided, write it to a file |
screamer | 13:ab47a20b66f0 | 237 | if options.build_report_junit: |
screamer | 13:ab47a20b66f0 | 238 | report_exporter = ReportExporter(ResultExporterType.JUNIT, package="build") |
screamer | 13:ab47a20b66f0 | 239 | report_exporter.report_to_file(build_report, options.build_report_junit, test_suite_properties=build_properties) |
screamer | 22:9e85236d8716 | 240 | |
screamer | 22:9e85236d8716 | 241 | # Print memory map summary on screen |
screamer | 22:9e85236d8716 | 242 | if build_report: |
screamer | 22:9e85236d8716 | 243 | |
screamer | 29:1210849dba19 | 244 | print print_build_memory_usage(build_report) |
screamer | 22:9e85236d8716 | 245 | |
screamer | 13:ab47a20b66f0 | 246 | print_report_exporter = ReportExporter(ResultExporterType.PRINT, package="build") |
screamer | 13:ab47a20b66f0 | 247 | status = print_report_exporter.report(build_report) |
screamer | 22:9e85236d8716 | 248 | |
screamer | 13:ab47a20b66f0 | 249 | if status: |
screamer | 13:ab47a20b66f0 | 250 | sys.exit(0) |
screamer | 13:ab47a20b66f0 | 251 | else: |
screamer | 13:ab47a20b66f0 | 252 | sys.exit(1) |
screamer | 0:66f3b5499f7f | 253 | |
screamer | 0:66f3b5499f7f | 254 | except KeyboardInterrupt, e: |
screamer | 0:66f3b5499f7f | 255 | print "\n[CTRL+c] exit" |
The Other Jimmy |
32:8ea194f6145b | 256 | except ConfigException, e: |
The Other Jimmy |
32:8ea194f6145b | 257 | # Catching ConfigException here to prevent a traceback |
The Other Jimmy |
32:8ea194f6145b | 258 | print "[ERROR] %s" % str(e) |
screamer | 0:66f3b5499f7f | 259 | except Exception,e: |
screamer | 0:66f3b5499f7f | 260 | import traceback |
screamer | 0:66f3b5499f7f | 261 | traceback.print_exc(file=sys.stdout) |
screamer | 0:66f3b5499f7f | 262 | print "[ERROR] %s" % str(e) |
screamer | 0:66f3b5499f7f | 263 | sys.exit(1) |