mbed os with nrf51 internal bandgap enabled to read battery level
Dependents: BLE_file_test BLE_Blink ExternalEncoder
tools/test/export/build_test.py@0:f269e3021894, 2016-10-23 (annotated)
- Committer:
- elessair
- Date:
- Sun Oct 23 15:10:02 2016 +0000
- Revision:
- 0:f269e3021894
Initial commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
elessair | 0:f269e3021894 | 1 | #!/usr/bin/env python |
elessair | 0:f269e3021894 | 2 | """ |
elessair | 0:f269e3021894 | 3 | mbed SDK |
elessair | 0:f269e3021894 | 4 | Copyright (c) 2011-2016 ARM Limited |
elessair | 0:f269e3021894 | 5 | |
elessair | 0:f269e3021894 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); |
elessair | 0:f269e3021894 | 7 | you may not use this file except in compliance with the License. |
elessair | 0:f269e3021894 | 8 | You may obtain a copy of the License at |
elessair | 0:f269e3021894 | 9 | |
elessair | 0:f269e3021894 | 10 | http://www.apache.org/licenses/LICENSE-2.0 |
elessair | 0:f269e3021894 | 11 | |
elessair | 0:f269e3021894 | 12 | Unless required by applicable law or agreed to in writing, software |
elessair | 0:f269e3021894 | 13 | distributed under the License is distributed on an "AS IS" BASIS, |
elessair | 0:f269e3021894 | 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
elessair | 0:f269e3021894 | 15 | See the License for the specific language governing permissions and |
elessair | 0:f269e3021894 | 16 | limitations under the License. |
elessair | 0:f269e3021894 | 17 | """ |
elessair | 0:f269e3021894 | 18 | |
elessair | 0:f269e3021894 | 19 | import sys |
elessair | 0:f269e3021894 | 20 | from os import remove, rename |
elessair | 0:f269e3021894 | 21 | from os.path import join, dirname, exists, abspath |
elessair | 0:f269e3021894 | 22 | ROOT = abspath(join(dirname(__file__), "..", "..", "..")) |
elessair | 0:f269e3021894 | 23 | sys.path.insert(0, ROOT) |
elessair | 0:f269e3021894 | 24 | import argparse |
elessair | 0:f269e3021894 | 25 | from argparse import ArgumentTypeError |
elessair | 0:f269e3021894 | 26 | import sys |
elessair | 0:f269e3021894 | 27 | from shutil import rmtree |
elessair | 0:f269e3021894 | 28 | from collections import namedtuple |
elessair | 0:f269e3021894 | 29 | from copy import copy |
elessair | 0:f269e3021894 | 30 | |
elessair | 0:f269e3021894 | 31 | |
elessair | 0:f269e3021894 | 32 | from tools.paths import EXPORT_DIR |
elessair | 0:f269e3021894 | 33 | from tools.tests import TESTS |
elessair | 0:f269e3021894 | 34 | from tools.build_api import get_mbed_official_release, RELEASE_VERSIONS |
elessair | 0:f269e3021894 | 35 | from tools.test_api import find_tests |
elessair | 0:f269e3021894 | 36 | from tools.project import export |
elessair | 0:f269e3021894 | 37 | from Queue import Queue |
elessair | 0:f269e3021894 | 38 | from threading import Thread, Lock |
elessair | 0:f269e3021894 | 39 | from tools.project_api import print_results, get_exporter_toolchain |
elessair | 0:f269e3021894 | 40 | from tools.tests import test_name_known, test_known, Test |
elessair | 0:f269e3021894 | 41 | from tools.export.exporters import FailedBuildException, \ |
elessair | 0:f269e3021894 | 42 | TargetNotSupportedException |
elessair | 0:f269e3021894 | 43 | from tools.utils import argparse_force_lowercase_type, \ |
elessair | 0:f269e3021894 | 44 | argparse_many, columnate, args_error, \ |
elessair | 0:f269e3021894 | 45 | argparse_filestring_type |
elessair | 0:f269e3021894 | 46 | from tools.options import extract_profile |
elessair | 0:f269e3021894 | 47 | |
elessair | 0:f269e3021894 | 48 | print_lock = Lock() |
elessair | 0:f269e3021894 | 49 | |
elessair | 0:f269e3021894 | 50 | def do_queue(Class, function, interable) : |
elessair | 0:f269e3021894 | 51 | q = Queue() |
elessair | 0:f269e3021894 | 52 | threads = [Class(q, function) for each in range(20)] |
elessair | 0:f269e3021894 | 53 | for thing in interable : |
elessair | 0:f269e3021894 | 54 | q.put(thing) |
elessair | 0:f269e3021894 | 55 | for each in threads : |
elessair | 0:f269e3021894 | 56 | each.setDaemon(True) |
elessair | 0:f269e3021894 | 57 | each.start() |
elessair | 0:f269e3021894 | 58 | q.join() |
elessair | 0:f269e3021894 | 59 | |
elessair | 0:f269e3021894 | 60 | |
elessair | 0:f269e3021894 | 61 | class Reader (Thread) : |
elessair | 0:f269e3021894 | 62 | def __init__(self, queue, func) : |
elessair | 0:f269e3021894 | 63 | Thread.__init__(self) |
elessair | 0:f269e3021894 | 64 | self.queue = queue |
elessair | 0:f269e3021894 | 65 | self.func = func |
elessair | 0:f269e3021894 | 66 | |
elessair | 0:f269e3021894 | 67 | def start(self) : |
elessair | 0:f269e3021894 | 68 | sys.stdout.flush() |
elessair | 0:f269e3021894 | 69 | while not self.queue.empty() : |
elessair | 0:f269e3021894 | 70 | test = self.queue.get() |
elessair | 0:f269e3021894 | 71 | self.func(test) |
elessair | 0:f269e3021894 | 72 | self.queue.task_done() |
elessair | 0:f269e3021894 | 73 | |
elessair | 0:f269e3021894 | 74 | |
elessair | 0:f269e3021894 | 75 | class ExportBuildTest(object): |
elessair | 0:f269e3021894 | 76 | """Object to encapsulate logic for progen build testing""" |
elessair | 0:f269e3021894 | 77 | def __init__(self, tests, parser, options): |
elessair | 0:f269e3021894 | 78 | """ |
elessair | 0:f269e3021894 | 79 | Initialize an instance of class ProgenBuildTest |
elessair | 0:f269e3021894 | 80 | Args: |
elessair | 0:f269e3021894 | 81 | tests: array of TestCase instances |
elessair | 0:f269e3021894 | 82 | """ |
elessair | 0:f269e3021894 | 83 | self.total = len(tests) |
elessair | 0:f269e3021894 | 84 | self.parser = parser |
elessair | 0:f269e3021894 | 85 | self.options = options |
elessair | 0:f269e3021894 | 86 | self.counter = 0 |
elessair | 0:f269e3021894 | 87 | self.successes = [] |
elessair | 0:f269e3021894 | 88 | self.failures = [] |
elessair | 0:f269e3021894 | 89 | self.skips = [] |
elessair | 0:f269e3021894 | 90 | self.tests = [ExportBuildTest.test_case(test) for test in tests] |
elessair | 0:f269e3021894 | 91 | self.build_queue = Queue() |
elessair | 0:f269e3021894 | 92 | |
elessair | 0:f269e3021894 | 93 | @staticmethod |
elessair | 0:f269e3021894 | 94 | def test_case(case): |
elessair | 0:f269e3021894 | 95 | TestCase = namedtuple('TestCase', case.keys()) |
elessair | 0:f269e3021894 | 96 | return TestCase(**case) |
elessair | 0:f269e3021894 | 97 | |
elessair | 0:f269e3021894 | 98 | def handle_log(self,log): |
elessair | 0:f269e3021894 | 99 | try: |
elessair | 0:f269e3021894 | 100 | with open(log, 'r') as in_log: |
elessair | 0:f269e3021894 | 101 | print in_log.read() |
elessair | 0:f269e3021894 | 102 | sys.stdout.flush() |
elessair | 0:f269e3021894 | 103 | log_name = join(EXPORT_DIR, dirname(log) + "_log.txt") |
elessair | 0:f269e3021894 | 104 | if exists(log_name): |
elessair | 0:f269e3021894 | 105 | # delete it if so |
elessair | 0:f269e3021894 | 106 | remove(log_name) |
elessair | 0:f269e3021894 | 107 | rename(log, log_name) |
elessair | 0:f269e3021894 | 108 | except IOError: |
elessair | 0:f269e3021894 | 109 | pass |
elessair | 0:f269e3021894 | 110 | |
elessair | 0:f269e3021894 | 111 | def batch_tests(self, clean=False): |
elessair | 0:f269e3021894 | 112 | """Performs all exports of self.tests |
elessair | 0:f269e3021894 | 113 | Peroform_exports will fill self.build_queue. |
elessair | 0:f269e3021894 | 114 | This function will empty self.build_queue and call the test's |
elessair | 0:f269e3021894 | 115 | IDE's build function.""" |
elessair | 0:f269e3021894 | 116 | do_queue(Reader, self.perform_exports, self.tests) |
elessair | 0:f269e3021894 | 117 | self.counter = 0 |
elessair | 0:f269e3021894 | 118 | self.total = self.build_queue.qsize() |
elessair | 0:f269e3021894 | 119 | while not self.build_queue.empty(): |
elessair | 0:f269e3021894 | 120 | build = self.build_queue.get() |
elessair | 0:f269e3021894 | 121 | self.counter +=1 |
elessair | 0:f269e3021894 | 122 | exporter = build[0] |
elessair | 0:f269e3021894 | 123 | test_case = build[1] |
elessair | 0:f269e3021894 | 124 | self.display_counter("Building test case %s::%s\t%s" |
elessair | 0:f269e3021894 | 125 | % (test_case.mcu, |
elessair | 0:f269e3021894 | 126 | test_case.ide, |
elessair | 0:f269e3021894 | 127 | test_case.name)) |
elessair | 0:f269e3021894 | 128 | try: |
elessair | 0:f269e3021894 | 129 | exporter.build() |
elessair | 0:f269e3021894 | 130 | except FailedBuildException: |
elessair | 0:f269e3021894 | 131 | self.failures.append("%s::%s\t%s" % (test_case.mcu, |
elessair | 0:f269e3021894 | 132 | test_case.ide, |
elessair | 0:f269e3021894 | 133 | test_case.name)) |
elessair | 0:f269e3021894 | 134 | else: |
elessair | 0:f269e3021894 | 135 | self.successes.append("%s::%s\t%s" % (test_case.mcu, |
elessair | 0:f269e3021894 | 136 | test_case.ide, |
elessair | 0:f269e3021894 | 137 | test_case.name)) |
elessair | 0:f269e3021894 | 138 | self.handle_log(exporter.generated_files[-1]) |
elessair | 0:f269e3021894 | 139 | if clean: |
elessair | 0:f269e3021894 | 140 | rmtree(exporter.export_dir) |
elessair | 0:f269e3021894 | 141 | |
elessair | 0:f269e3021894 | 142 | def display_counter (self, message) : |
elessair | 0:f269e3021894 | 143 | with print_lock: |
elessair | 0:f269e3021894 | 144 | sys.stdout.write("{}/{} {}".format(self.counter, self.total, |
elessair | 0:f269e3021894 | 145 | message) +"\n") |
elessair | 0:f269e3021894 | 146 | sys.stdout.flush() |
elessair | 0:f269e3021894 | 147 | |
elessair | 0:f269e3021894 | 148 | def perform_exports(self, test_case): |
elessair | 0:f269e3021894 | 149 | """ |
elessair | 0:f269e3021894 | 150 | Generate the project file for test_case and fill self.build_queue |
elessair | 0:f269e3021894 | 151 | Args: |
elessair | 0:f269e3021894 | 152 | test_case: object of type TestCase |
elessair | 0:f269e3021894 | 153 | """ |
elessair | 0:f269e3021894 | 154 | sys.stdout.flush() |
elessair | 0:f269e3021894 | 155 | self.counter += 1 |
elessair | 0:f269e3021894 | 156 | name_str = ('%s_%s_%s') % (test_case.mcu, test_case.ide, test_case.name) |
elessair | 0:f269e3021894 | 157 | self.display_counter("Exporting test case %s::%s\t%s" % (test_case.mcu, |
elessair | 0:f269e3021894 | 158 | test_case.ide, |
elessair | 0:f269e3021894 | 159 | test_case.name)) |
elessair | 0:f269e3021894 | 160 | |
elessair | 0:f269e3021894 | 161 | try: |
elessair | 0:f269e3021894 | 162 | _, toolchain = get_exporter_toolchain(test_case.ide) |
elessair | 0:f269e3021894 | 163 | profile = extract_profile(self.parser, self.options, toolchain) |
elessair | 0:f269e3021894 | 164 | exporter = export(test_case.mcu, test_case.ide, |
elessair | 0:f269e3021894 | 165 | project_id=test_case.id, zip_proj=None, |
elessair | 0:f269e3021894 | 166 | clean=True, src=test_case.src, |
elessair | 0:f269e3021894 | 167 | export_path=join(EXPORT_DIR,name_str), |
elessair | 0:f269e3021894 | 168 | silent=True, build_profile=profile) |
elessair | 0:f269e3021894 | 169 | exporter.generated_files.append(join(EXPORT_DIR,name_str,test_case.log)) |
elessair | 0:f269e3021894 | 170 | self.build_queue.put((exporter,test_case)) |
elessair | 0:f269e3021894 | 171 | except TargetNotSupportedException: |
elessair | 0:f269e3021894 | 172 | self.skips.append("%s::%s\t%s" % (test_case.mcu, test_case.ide, |
elessair | 0:f269e3021894 | 173 | test_case.name)) |
elessair | 0:f269e3021894 | 174 | # Check if the specified name is in all_os_tests |
elessair | 0:f269e3021894 | 175 | |
elessair | 0:f269e3021894 | 176 | |
elessair | 0:f269e3021894 | 177 | def check_valid_mbed_os(test): |
elessair | 0:f269e3021894 | 178 | """Check if the specified name is in all_os_tests |
elessair | 0:f269e3021894 | 179 | args: |
elessair | 0:f269e3021894 | 180 | test: string name to index all_os_tests |
elessair | 0:f269e3021894 | 181 | returns: tuple of test_name and source location of test, |
elessair | 0:f269e3021894 | 182 | as given by find_tests""" |
elessair | 0:f269e3021894 | 183 | all_os_tests = find_tests(ROOT, "K64F", "ARM") |
elessair | 0:f269e3021894 | 184 | if test in all_os_tests.keys(): |
elessair | 0:f269e3021894 | 185 | return (test, all_os_tests[test]) |
elessair | 0:f269e3021894 | 186 | else: |
elessair | 0:f269e3021894 | 187 | supported = columnate([t for t in all_os_tests.keys()]) |
elessair | 0:f269e3021894 | 188 | raise ArgumentTypeError("Program with name '{0}' not found. " |
elessair | 0:f269e3021894 | 189 | "Supported tests are: \n{1}".format(test,supported)) |
elessair | 0:f269e3021894 | 190 | |
elessair | 0:f269e3021894 | 191 | |
elessair | 0:f269e3021894 | 192 | def check_version(version): |
elessair | 0:f269e3021894 | 193 | """Check if the specified version is valid |
elessair | 0:f269e3021894 | 194 | args: |
elessair | 0:f269e3021894 | 195 | version: integer versio of mbed |
elessair | 0:f269e3021894 | 196 | returns: |
elessair | 0:f269e3021894 | 197 | version if it is valid""" |
elessair | 0:f269e3021894 | 198 | if version not in RELEASE_VERSIONS: |
elessair | 0:f269e3021894 | 199 | raise ArgumentTypeError("Choose from versions : %s"%", ".join(RELEASE_VERSIONS)) |
elessair | 0:f269e3021894 | 200 | return version |
elessair | 0:f269e3021894 | 201 | |
elessair | 0:f269e3021894 | 202 | |
elessair | 0:f269e3021894 | 203 | def main(): |
elessair | 0:f269e3021894 | 204 | """Entry point""" |
elessair | 0:f269e3021894 | 205 | |
elessair | 0:f269e3021894 | 206 | ide_list = ["iar", "uvision"] |
elessair | 0:f269e3021894 | 207 | |
elessair | 0:f269e3021894 | 208 | default_v2 = [test_name_known("MBED_BLINKY")] |
elessair | 0:f269e3021894 | 209 | default_v5 = [check_valid_mbed_os('tests-mbedmicro-rtos-mbed-basic')] |
elessair | 0:f269e3021894 | 210 | |
elessair | 0:f269e3021894 | 211 | parser = argparse.ArgumentParser(description= |
elessair | 0:f269e3021894 | 212 | "Test progen builders. Leave any flag off" |
elessair | 0:f269e3021894 | 213 | " to run with all possible options.") |
elessair | 0:f269e3021894 | 214 | parser.add_argument("-i", |
elessair | 0:f269e3021894 | 215 | dest="ides", |
elessair | 0:f269e3021894 | 216 | default=ide_list, |
elessair | 0:f269e3021894 | 217 | type=argparse_many(argparse_force_lowercase_type( |
elessair | 0:f269e3021894 | 218 | ide_list, "toolchain")), |
elessair | 0:f269e3021894 | 219 | help="The target IDE: %s"% str(ide_list)) |
elessair | 0:f269e3021894 | 220 | |
elessair | 0:f269e3021894 | 221 | parser.add_argument( "-p", |
elessair | 0:f269e3021894 | 222 | type=argparse_many(test_known), |
elessair | 0:f269e3021894 | 223 | dest="programs", |
elessair | 0:f269e3021894 | 224 | help="The index of the desired test program: [0-%d]" |
elessair | 0:f269e3021894 | 225 | % (len(TESTS) - 1)) |
elessair | 0:f269e3021894 | 226 | |
elessair | 0:f269e3021894 | 227 | parser.add_argument("-n", |
elessair | 0:f269e3021894 | 228 | type=argparse_many(test_name_known), |
elessair | 0:f269e3021894 | 229 | dest="programs", |
elessair | 0:f269e3021894 | 230 | help="The name of the desired test program") |
elessair | 0:f269e3021894 | 231 | |
elessair | 0:f269e3021894 | 232 | parser.add_argument("-m", "--mcu", |
elessair | 0:f269e3021894 | 233 | help=("Generate projects for the given MCUs"), |
elessair | 0:f269e3021894 | 234 | metavar="MCU", |
elessair | 0:f269e3021894 | 235 | type=argparse_many(str.upper)) |
elessair | 0:f269e3021894 | 236 | |
elessair | 0:f269e3021894 | 237 | parser.add_argument("-os-tests", |
elessair | 0:f269e3021894 | 238 | type=argparse_many(check_valid_mbed_os), |
elessair | 0:f269e3021894 | 239 | dest="os_tests", |
elessair | 0:f269e3021894 | 240 | help="Mbed-os tests") |
elessair | 0:f269e3021894 | 241 | |
elessair | 0:f269e3021894 | 242 | parser.add_argument("-c", "--clean", |
elessair | 0:f269e3021894 | 243 | dest="clean", |
elessair | 0:f269e3021894 | 244 | action="store_true", |
elessair | 0:f269e3021894 | 245 | help="clean up the exported project files", |
elessair | 0:f269e3021894 | 246 | default=False) |
elessair | 0:f269e3021894 | 247 | |
elessair | 0:f269e3021894 | 248 | parser.add_argument("--release", |
elessair | 0:f269e3021894 | 249 | dest="release", |
elessair | 0:f269e3021894 | 250 | type=check_version, |
elessair | 0:f269e3021894 | 251 | help="Which version of mbed to test", |
elessair | 0:f269e3021894 | 252 | default=RELEASE_VERSIONS[-1]) |
elessair | 0:f269e3021894 | 253 | |
elessair | 0:f269e3021894 | 254 | parser.add_argument("--profile", |
elessair | 0:f269e3021894 | 255 | dest="profile", |
elessair | 0:f269e3021894 | 256 | action="append", |
elessair | 0:f269e3021894 | 257 | type=argparse_filestring_type, |
elessair | 0:f269e3021894 | 258 | default=[]) |
elessair | 0:f269e3021894 | 259 | |
elessair | 0:f269e3021894 | 260 | options = parser.parse_args() |
elessair | 0:f269e3021894 | 261 | # targets in chosen release |
elessair | 0:f269e3021894 | 262 | targetnames = [target[0] for target in |
elessair | 0:f269e3021894 | 263 | get_mbed_official_release(options.release)] |
elessair | 0:f269e3021894 | 264 | # all targets in release are default |
elessair | 0:f269e3021894 | 265 | test_targets = options.mcu or targetnames |
elessair | 0:f269e3021894 | 266 | if not all([t in targetnames for t in test_targets]): |
elessair | 0:f269e3021894 | 267 | args_error(parser, "Only specify targets in release %s:\n%s" |
elessair | 0:f269e3021894 | 268 | %(options.release, columnate(targetnames))) |
elessair | 0:f269e3021894 | 269 | |
elessair | 0:f269e3021894 | 270 | v2_tests, v5_tests = [],[] |
elessair | 0:f269e3021894 | 271 | if options.release == '5': |
elessair | 0:f269e3021894 | 272 | v5_tests = options.os_tests or default_v5 |
elessair | 0:f269e3021894 | 273 | elif options.release == '2': |
elessair | 0:f269e3021894 | 274 | v2_tests = options.programs or default_v2 |
elessair | 0:f269e3021894 | 275 | |
elessair | 0:f269e3021894 | 276 | tests = [] |
elessair | 0:f269e3021894 | 277 | default_test = {key:None for key in ['ide', 'mcu', 'name', 'id', 'src', 'log']} |
elessair | 0:f269e3021894 | 278 | for mcu in test_targets: |
elessair | 0:f269e3021894 | 279 | for ide in options.ides: |
elessair | 0:f269e3021894 | 280 | log = "build_log.txt" if ide == 'iar' \ |
elessair | 0:f269e3021894 | 281 | else join('build', 'build_log.txt') |
elessair | 0:f269e3021894 | 282 | # add each test case to the tests array |
elessair | 0:f269e3021894 | 283 | default_test.update({'mcu': mcu, 'ide': ide, 'log':log}) |
elessair | 0:f269e3021894 | 284 | for test in v2_tests: |
elessair | 0:f269e3021894 | 285 | default_test.update({'name':TESTS[test]["id"], 'id':test}) |
elessair | 0:f269e3021894 | 286 | tests.append(copy(default_test)) |
elessair | 0:f269e3021894 | 287 | for test in v5_tests: |
elessair | 0:f269e3021894 | 288 | default_test.update({'name':test[0],'src':[test[1],ROOT]}) |
elessair | 0:f269e3021894 | 289 | tests.append(copy(default_test)) |
elessair | 0:f269e3021894 | 290 | test = ExportBuildTest(tests, parser, options) |
elessair | 0:f269e3021894 | 291 | test.batch_tests(clean=options.clean) |
elessair | 0:f269e3021894 | 292 | print_results(test.successes, test.failures, test.skips) |
elessair | 0:f269e3021894 | 293 | sys.exit(len(test.failures)) |
elessair | 0:f269e3021894 | 294 | |
elessair | 0:f269e3021894 | 295 | if __name__ == "__main__": |
elessair | 0:f269e3021894 | 296 | main() |