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: BLE_file_test BLE_Blink ExternalEncoder
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 from argparse import ArgumentTypeError 00026 import sys 00027 from shutil import rmtree 00028 from collections import namedtuple 00029 from copy import copy 00030 00031 00032 from tools.paths import EXPORT_DIR 00033 from tools.tests import TESTS 00034 from tools.build_api import get_mbed_official_release, RELEASE_VERSIONS 00035 from tools.test_api import find_tests 00036 from tools.project import export 00037 from Queue import Queue 00038 from threading import Thread, Lock 00039 from tools.project_api import print_results, get_exporter_toolchain 00040 from tools.tests import test_name_known, test_known, Test 00041 from tools.export.exporters import FailedBuildException, \ 00042 TargetNotSupportedException 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 try: 00129 exporter.build() 00130 except FailedBuildException: 00131 self.failures .append("%s::%s\t%s" % (test_case.mcu, 00132 test_case.ide, 00133 test_case.name)) 00134 else: 00135 self.successes .append("%s::%s\t%s" % (test_case.mcu, 00136 test_case.ide, 00137 test_case.name)) 00138 self.handle_log (exporter.generated_files[-1]) 00139 if clean: 00140 rmtree(exporter.export_dir) 00141 00142 def display_counter (self, message) : 00143 with print_lock: 00144 sys.stdout.write("{}/{} {}".format(self.counter , self.total , 00145 message) +"\n") 00146 sys.stdout.flush() 00147 00148 def perform_exports (self, test_case): 00149 """ 00150 Generate the project file for test_case and fill self.build_queue 00151 Args: 00152 test_case: object of type TestCase 00153 """ 00154 sys.stdout.flush() 00155 self.counter += 1 00156 name_str = ('%s_%s_%s') % (test_case.mcu, test_case.ide, test_case.name) 00157 self.display_counter ("Exporting test case %s::%s\t%s" % (test_case.mcu, 00158 test_case.ide, 00159 test_case.name)) 00160 00161 try: 00162 _, toolchain = get_exporter_toolchain(test_case.ide) 00163 profile = extract_profile(self.parser , self.options , toolchain) 00164 exporter = export(test_case.mcu, test_case.ide, 00165 project_id=test_case.id, zip_proj=None, 00166 clean=True, src=test_case.src, 00167 export_path=join(EXPORT_DIR,name_str), 00168 silent=True, build_profile=profile) 00169 exporter.generated_files.append(join(EXPORT_DIR,name_str,test_case.log)) 00170 self.build_queue .put((exporter,test_case)) 00171 except TargetNotSupportedException: 00172 self.skips .append("%s::%s\t%s" % (test_case.mcu, test_case.ide, 00173 test_case.name)) 00174 # Check if the specified name is in all_os_tests 00175 00176 00177 def check_valid_mbed_os(test): 00178 """Check if the specified name is in all_os_tests 00179 args: 00180 test: string name to index all_os_tests 00181 returns: tuple of test_name and source location of test, 00182 as given by find_tests""" 00183 all_os_tests = find_tests(ROOT, "K64F", "ARM") 00184 if test in all_os_tests.keys(): 00185 return (test, all_os_tests[test]) 00186 else: 00187 supported = columnate([t for t in all_os_tests.keys()]) 00188 raise ArgumentTypeError("Program with name '{0}' not found. " 00189 "Supported tests are: \n{1}".format(test,supported)) 00190 00191 00192 def check_version(version): 00193 """Check if the specified version is valid 00194 args: 00195 version: integer versio of mbed 00196 returns: 00197 version if it is valid""" 00198 if version not in RELEASE_VERSIONS: 00199 raise ArgumentTypeError("Choose from versions : %s"%", ".join(RELEASE_VERSIONS)) 00200 return version 00201 00202 00203 def main(): 00204 """Entry point""" 00205 00206 ide_list = ["iar", "uvision"] 00207 00208 default_v2 = [test_name_known("MBED_BLINKY")] 00209 default_v5 = [check_valid_mbed_os('tests-mbedmicro-rtos-mbed-basic')] 00210 00211 parser = argparse.ArgumentParser(description= 00212 "Test progen builders. Leave any flag off" 00213 " to run with all possible options.") 00214 parser.add_argument("-i", 00215 dest="ides", 00216 default=ide_list, 00217 type=argparse_many(argparse_force_lowercase_type( 00218 ide_list, "toolchain")), 00219 help="The target IDE: %s"% str(ide_list)) 00220 00221 parser.add_argument( "-p", 00222 type=argparse_many(test_known), 00223 dest="programs", 00224 help="The index of the desired test program: [0-%d]" 00225 % (len(TESTS) - 1)) 00226 00227 parser.add_argument("-n", 00228 type=argparse_many(test_name_known), 00229 dest="programs", 00230 help="The name of the desired test program") 00231 00232 parser.add_argument("-m", "--mcu", 00233 help=("Generate projects for the given MCUs"), 00234 metavar="MCU", 00235 type=argparse_many(str.upper)) 00236 00237 parser.add_argument("-os-tests", 00238 type=argparse_many(check_valid_mbed_os), 00239 dest="os_tests", 00240 help="Mbed-os tests") 00241 00242 parser.add_argument("-c", "--clean", 00243 dest="clean", 00244 action="store_true", 00245 help="clean up the exported project files", 00246 default=False) 00247 00248 parser.add_argument("--release", 00249 dest="release", 00250 type=check_version, 00251 help="Which version of mbed to test", 00252 default=RELEASE_VERSIONS[-1]) 00253 00254 parser.add_argument("--profile", 00255 dest="profile", 00256 action="append", 00257 type=argparse_filestring_type, 00258 default=[]) 00259 00260 options = parser.parse_args() 00261 # targets in chosen release 00262 targetnames = [target[0] for target in 00263 get_mbed_official_release(options.release)] 00264 # all targets in release are default 00265 test_targets = options.mcu or targetnames 00266 if not all([t in targetnames for t in test_targets]): 00267 args_error(parser, "Only specify targets in release %s:\n%s" 00268 %(options.release, columnate(targetnames))) 00269 00270 v2_tests, v5_tests = [],[] 00271 if options.release == '5': 00272 v5_tests = options.os_tests or default_v5 00273 elif options.release == '2': 00274 v2_tests = options.programs or default_v2 00275 00276 tests = [] 00277 default_test = {key:None for key in ['ide', 'mcu', 'name', 'id', 'src', 'log']} 00278 for mcu in test_targets: 00279 for ide in options.ides: 00280 log = "build_log.txt" if ide == 'iar' \ 00281 else join('build', 'build_log.txt') 00282 # add each test case to the tests array 00283 default_test.update({'mcu': mcu, 'ide': ide, 'log':log}) 00284 for test in v2_tests: 00285 default_test.update({'name':TESTS[test]["id"], 'id':test}) 00286 tests.append(copy(default_test)) 00287 for test in v5_tests: 00288 default_test.update({'name':test[0],'src':[test[1],ROOT]}) 00289 tests.append(copy(default_test)) 00290 test = ExportBuildTest(tests, parser, options) 00291 test.batch_tests(clean=options.clean) 00292 print_results(test.successes, test.failures, test.skips) 00293 sys.exit(len(test.failures)) 00294 00295 if __name__ == "__main__": 00296 main()
Generated on Tue Jul 12 2022 15:19:23 by
