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.
Dependents: mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510
build_test.py
00001 #!/usr/bin/env python 00002 """ 00003 mbed SDK 00004 Copyright (c) 2011-2016 ARM Limited 00005 00006 Licensed under the Apache License, Version 2.0 (the "License"); 00007 you may not use this file except in compliance with the License. 00008 You may obtain a copy of the License at 00009 00010 http://www.apache.org/licenses/LICENSE-2.0 00011 00012 Unless required by applicable law or agreed to in writing, software 00013 distributed under the License is distributed on an "AS IS" BASIS, 00014 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 See the License for the specific language governing permissions and 00016 limitations under the License. 00017 """ 00018 00019 import sys 00020 from os import remove, rename 00021 from os.path import join, dirname, exists, abspath 00022 ROOT = abspath(join(dirname(__file__), "..", "..", "..")) 00023 sys.path.insert(0, ROOT) 00024 import argparse 00025 import os 00026 from argparse import ArgumentTypeError 00027 import sys 00028 from shutil import rmtree 00029 from collections import namedtuple 00030 from copy import copy 00031 00032 00033 from tools.paths import EXPORT_DIR 00034 from tools.tests import TESTS 00035 from tools.build_api import get_mbed_official_release, RELEASE_VERSIONS 00036 from tools.test_api import find_tests 00037 from tools.project import export 00038 from Queue import Queue 00039 from threading import Thread, Lock 00040 from tools.project_api import print_results, get_exporter_toolchain 00041 from tools.tests import test_name_known, test_known 00042 from tools.export import EXPORTERS 00043 from tools.utils import argparse_force_lowercase_type, \ 00044 argparse_many, columnate, args_error, \ 00045 argparse_filestring_type 00046 from tools.options import extract_profile 00047 00048 print_lock = Lock() 00049 00050 def do_queue(Class, function, interable) : 00051 q = Queue() 00052 threads = [Class(q, function) for each in range(20)] 00053 for thing in interable : 00054 q.put(thing) 00055 for each in threads : 00056 each.setDaemon(True) 00057 each.start() 00058 q.join() 00059 00060 00061 class Reader (Thread) : 00062 def __init__(self, queue, func) : 00063 Thread.__init__(self) 00064 self.queue = queue 00065 self.func = func 00066 00067 def start(self) : 00068 sys.stdout.flush() 00069 while not self.queue.empty() : 00070 test = self.queue.get() 00071 self.func(test) 00072 self.queue.task_done() 00073 00074 00075 class ExportBuildTest (object): 00076 """Object to encapsulate logic for progen build testing""" 00077 def __init__ (self, tests, parser, options): 00078 """ 00079 Initialize an instance of class ProgenBuildTest 00080 Args: 00081 tests: array of TestCase instances 00082 """ 00083 self.total = len(tests) 00084 self.parser = parser 00085 self.options = options 00086 self.counter = 0 00087 self.successes = [] 00088 self.failures = [] 00089 self.skips = [] 00090 self.tests = [ExportBuildTest.test_case(test) for test in tests] 00091 self.build_queue = Queue() 00092 00093 @staticmethod 00094 def test_case(case): 00095 TestCase = namedtuple('TestCase', case.keys()) 00096 return TestCase(**case) 00097 00098 def handle_log(self,log): 00099 try: 00100 with open(log, 'r') as in_log: 00101 print in_log.read() 00102 sys.stdout.flush() 00103 log_name = join(EXPORT_DIR, dirname(log) + "_log.txt") 00104 if exists(log_name): 00105 # delete it if so 00106 remove(log_name) 00107 rename(log, log_name) 00108 except IOError: 00109 pass 00110 00111 def batch_tests (self, clean=False): 00112 """Performs all exports of self.tests 00113 Peroform_exports will fill self.build_queue. 00114 This function will empty self.build_queue and call the test's 00115 IDE's build function.""" 00116 do_queue(Reader, self.perform_exports , self.tests ) 00117 self.counter = 0 00118 self.total = self.build_queue .qsize() 00119 while not self.build_queue .empty(): 00120 build = self.build_queue .get() 00121 self.counter +=1 00122 exporter = build[0] 00123 test_case = build[1] 00124 self.display_counter ("Building test case %s::%s\t%s" 00125 % (test_case.mcu, 00126 test_case.ide, 00127 test_case.name)) 00128 00129 cwd = os.getcwd() 00130 os.chdir(exporter.export_dir) 00131 res = EXPORTERS[exporter.NAME.lower()].build(exporter.project_name, cleanup=False) 00132 os.chdir(cwd) 00133 if res: 00134 self.failures .append("%s::%s\t%s" % (test_case.mcu, 00135 test_case.ide, 00136 test_case.name)) 00137 else: 00138 self.successes .append("%s::%s\t%s" % (test_case.mcu, 00139 test_case.ide, 00140 test_case.name)) 00141 self.handle_log (exporter.generated_files[-1]) 00142 if clean: 00143 rmtree(exporter.export_dir) 00144 00145 def display_counter (self, message) : 00146 with print_lock: 00147 sys.stdout.write("{}/{} {}".format(self.counter , self.total , 00148 message) +"\n") 00149 sys.stdout.flush() 00150 00151 def perform_exports (self, test_case): 00152 """ 00153 Generate the project file for test_case and fill self.build_queue 00154 Args: 00155 test_case: object of type TestCase 00156 """ 00157 sys.stdout.flush() 00158 self.counter += 1 00159 name_str = ('%s_%s_%s') % (test_case.mcu, test_case.ide, test_case.name) 00160 self.display_counter ("Exporting test case %s::%s\t%s" % (test_case.mcu, 00161 test_case.ide, 00162 test_case.name)) 00163 exporter, toolchain = get_exporter_toolchain(test_case.ide) 00164 if test_case.mcu not in exporter.TARGETS: 00165 self.skips .append("%s::%s\t%s" % (test_case.mcu, test_case.ide, 00166 test_case.name)) 00167 return 00168 profile = extract_profile(self.parser , self.options , toolchain) 00169 exporter = export(test_case.mcu, test_case.ide, 00170 project_id=test_case.id, zip_proj=None, 00171 src=test_case.src, 00172 export_path=join(EXPORT_DIR, name_str), 00173 silent=True, build_profile=profile) 00174 exporter.generated_files.append(join(EXPORT_DIR,name_str,test_case.log)) 00175 self.build_queue .put((exporter,test_case)) 00176 # Check if the specified name is in all_os_tests 00177 00178 00179 def check_valid_mbed_os(test): 00180 """Check if the specified name is in all_os_tests 00181 args: 00182 test: string name to index all_os_tests 00183 returns: tuple of test_name and source location of test, 00184 as given by find_tests""" 00185 all_os_tests = find_tests(ROOT, "K64F", "ARM") 00186 if test in all_os_tests.keys(): 00187 return (test, all_os_tests[test]) 00188 else: 00189 supported = columnate([t for t in all_os_tests.keys()]) 00190 raise ArgumentTypeError("Program with name '{0}' not found. " 00191 "Supported tests are: \n{1}".format(test,supported)) 00192 00193 00194 def check_version(version): 00195 """Check if the specified version is valid 00196 args: 00197 version: integer versio of mbed 00198 returns: 00199 version if it is valid""" 00200 if version not in RELEASE_VERSIONS: 00201 raise ArgumentTypeError("Choose from versions : %s"%", ".join(RELEASE_VERSIONS)) 00202 return version 00203 00204 00205 def main(): 00206 """Entry point""" 00207 00208 ide_list = ["iar", "uvision"] 00209 00210 default_v2 = [test_name_known("MBED_BLINKY")] 00211 default_v5 = [check_valid_mbed_os('tests-mbedmicro-rtos-mbed-basic')] 00212 00213 parser = argparse.ArgumentParser(description= 00214 "Test progen builders. Leave any flag off" 00215 " to run with all possible options.") 00216 parser.add_argument("-i", 00217 dest="ides", 00218 default=ide_list, 00219 type=argparse_many(argparse_force_lowercase_type( 00220 ide_list, "toolchain")), 00221 help="The target IDE: %s"% str(ide_list)) 00222 00223 parser.add_argument( "-p", 00224 type=argparse_many(test_known), 00225 dest="programs", 00226 help="The index of the desired test program: [0-%d]" 00227 % (len(TESTS) - 1)) 00228 00229 parser.add_argument("-n", 00230 type=argparse_many(test_name_known), 00231 dest="programs", 00232 help="The name of the desired test program") 00233 00234 parser.add_argument("-m", "--mcu", 00235 help=("Generate projects for the given MCUs"), 00236 metavar="MCU", 00237 type=argparse_many(str.upper)) 00238 00239 parser.add_argument("-os-tests", 00240 type=argparse_many(check_valid_mbed_os), 00241 dest="os_tests", 00242 help="Mbed-os tests") 00243 00244 parser.add_argument("-c", "--clean", 00245 dest="clean", 00246 action="store_true", 00247 help="clean up the exported project files", 00248 default=False) 00249 00250 parser.add_argument("--release", 00251 dest="release", 00252 type=check_version, 00253 help="Which version of mbed to test", 00254 default=RELEASE_VERSIONS[-1]) 00255 00256 parser.add_argument("--profile", 00257 dest="profile", 00258 action="append", 00259 type=argparse_filestring_type, 00260 default=[]) 00261 00262 options = parser.parse_args() 00263 # targets in chosen release 00264 targetnames = [target[0] for target in 00265 get_mbed_official_release(options.release)] 00266 # all targets in release are default 00267 test_targets = options.mcu or targetnames 00268 if not all([t in targetnames for t in test_targets]): 00269 args_error(parser, "Only specify targets in release %s:\n%s" 00270 %(options.release, columnate(sorted(targetnames)))) 00271 00272 v2_tests, v5_tests = [],[] 00273 if options.release == '5': 00274 v5_tests = options.os_tests or default_v5 00275 elif options.release == '2': 00276 v2_tests = options.programs or default_v2 00277 00278 tests = [] 00279 default_test = {key:None for key in ['ide', 'mcu', 'name', 'id', 'src', 'log']} 00280 for mcu in test_targets: 00281 for ide in options.ides: 00282 log = "build_log.txt" if ide == 'iar' \ 00283 else join('build', 'build_log.txt') 00284 # add each test case to the tests array 00285 default_test.update({'mcu': mcu, 'ide': ide, 'log':log}) 00286 for test in v2_tests: 00287 default_test.update({'name':TESTS[test]["id"], 'id':test}) 00288 tests.append(copy(default_test)) 00289 for test in v5_tests: 00290 default_test.update({'name':test[0],'src':[test[1],ROOT]}) 00291 tests.append(copy(default_test)) 00292 test = ExportBuildTest(tests, parser, options) 00293 test.batch_tests(clean=options.clean) 00294 print_results(test.successes, test.failures, test.skips) 00295 sys.exit(len(test.failures)) 00296 00297 if __name__ == "__main__": 00298 main()
Generated on Tue Jul 12 2022 11:02:33 by
