166a7a246SJörg Krause#!/usr/bin/env python2 283d290c5STom Rini# SPDX-License-Identifier: GPL-2.0+ 3bf7fd50bSSimon Glass 4bf7fd50bSSimon Glass# Copyright (c) 2016 Google, Inc 5bf7fd50bSSimon Glass# Written by Simon Glass <sjg@chromium.org> 6bf7fd50bSSimon Glass# 7bf7fd50bSSimon Glass# Creates binary images from input files controlled by a description 8bf7fd50bSSimon Glass# 9bf7fd50bSSimon Glass 10bf7fd50bSSimon Glass"""See README for more information""" 11bf7fd50bSSimon Glass 12a25ebed3SSimon Glassimport glob 13*11ae93eeSSimon Glassimport multiprocessing 14bf7fd50bSSimon Glassimport os 15bf7fd50bSSimon Glassimport sys 16bf7fd50bSSimon Glassimport traceback 17bf7fd50bSSimon Glassimport unittest 18bf7fd50bSSimon Glass 19bf7fd50bSSimon Glass# Bring in the patman and dtoc libraries 20bf7fd50bSSimon Glassour_path = os.path.dirname(os.path.realpath(__file__)) 21*11ae93eeSSimon Glassfor dirname in ['../patman', '../dtoc', '..', '../concurrencytest']: 227feccfdcSSimon Glass sys.path.insert(0, os.path.join(our_path, dirname)) 23bf7fd50bSSimon Glass 24b4360206SSimon Glass# Bring in the libfdt module 2515b97f5cSMasahiro Yamadasys.path.insert(0, 'scripts/dtc/pylibfdt') 26ed59e005SSimon Glasssys.path.insert(0, os.path.join(our_path, 27ed59e005SSimon Glass '../../build-sandbox_spl/scripts/dtc/pylibfdt')) 28b4360206SSimon Glass 29bf7fd50bSSimon Glassimport cmdline 30bf7fd50bSSimon Glassimport command 31*11ae93eeSSimon Glassuse_concurrent = True 32*11ae93eeSSimon Glasstry: 33*11ae93eeSSimon Glass from concurrencytest import ConcurrentTestSuite, fork_for_tests 34*11ae93eeSSimon Glassexcept: 35*11ae93eeSSimon Glass use_concurrent = False 36bf7fd50bSSimon Glassimport control 37ff1fd6ccSSimon Glassimport test_util 38bf7fd50bSSimon Glass 39*11ae93eeSSimon Glassdef RunTests(debug, processes, args): 40084059a3SSimon Glass """Run the functional tests and any embedded doctests 41084059a3SSimon Glass 42084059a3SSimon Glass Args: 43084059a3SSimon Glass debug: True to enable debugging, which shows a full stack trace on error 44084059a3SSimon Glass args: List of positional args provided to binman. This can hold a test 45084059a3SSimon Glass name to execute (as in 'binman -t testSections', for example) 46*11ae93eeSSimon Glass processes: Number of processes to use to run tests (None=same as #CPUs) 47084059a3SSimon Glass """ 48b50e5611SSimon Glass import elf_test 49bf7fd50bSSimon Glass import entry_test 50bf7fd50bSSimon Glass import fdt_test 51680e3312SSimon Glass import ftest 5219790632SSimon Glass import image_test 53bf7fd50bSSimon Glass import test 54bf7fd50bSSimon Glass import doctest 55bf7fd50bSSimon Glass 56bf7fd50bSSimon Glass result = unittest.TestResult() 57bf7fd50bSSimon Glass for module in []: 58bf7fd50bSSimon Glass suite = doctest.DocTestSuite(module) 59bf7fd50bSSimon Glass suite.run(result) 60bf7fd50bSSimon Glass 61bf7fd50bSSimon Glass sys.argv = [sys.argv[0]] 627fe9173bSSimon Glass if debug: 637fe9173bSSimon Glass sys.argv.append('-D') 64*11ae93eeSSimon Glass if debug: 65*11ae93eeSSimon Glass sys.argv.append('-D') 66934cdcfbSSimon Glass 67934cdcfbSSimon Glass # Run the entry tests first ,since these need to be the first to import the 68934cdcfbSSimon Glass # 'entry' module. 69084059a3SSimon Glass test_name = args and args[0] or None 70*11ae93eeSSimon Glass suite = unittest.TestSuite() 71*11ae93eeSSimon Glass loader = unittest.TestLoader() 722cd01285SSimon Glass for module in (entry_test.TestEntry, ftest.TestFunctional, fdt_test.TestFdt, 732cd01285SSimon Glass elf_test.TestElf, image_test.TestImage): 74084059a3SSimon Glass if test_name: 75084059a3SSimon Glass try: 76*11ae93eeSSimon Glass suite.addTests(loader.loadTestsFromName(test_name, module)) 77084059a3SSimon Glass except AttributeError: 78084059a3SSimon Glass continue 79084059a3SSimon Glass else: 80*11ae93eeSSimon Glass suite.addTests(loader.loadTestsFromTestCase(module)) 81*11ae93eeSSimon Glass if use_concurrent and processes != 1: 82*11ae93eeSSimon Glass concurrent_suite = ConcurrentTestSuite(suite, 83*11ae93eeSSimon Glass fork_for_tests(processes or multiprocessing.cpu_count())) 84*11ae93eeSSimon Glass concurrent_suite.run(result) 85*11ae93eeSSimon Glass else: 86bf7fd50bSSimon Glass suite.run(result) 87bf7fd50bSSimon Glass 88bf7fd50bSSimon Glass print result 89bf7fd50bSSimon Glass for test, err in result.errors: 90bf7fd50bSSimon Glass print test.id(), err 91bf7fd50bSSimon Glass for test, err in result.failures: 929677faa3SSimon Glass print err, result.failures 939677faa3SSimon Glass if result.errors or result.failures: 949677faa3SSimon Glass print 'binman tests FAILED' 959677faa3SSimon Glass return 1 969677faa3SSimon Glass return 0 97bf7fd50bSSimon Glass 98fd8d1f79SSimon Glassdef GetEntryModules(include_testing=True): 99fd8d1f79SSimon Glass """Get a set of entry class implementations 100fd8d1f79SSimon Glass 101fd8d1f79SSimon Glass Returns: 102fd8d1f79SSimon Glass Set of paths to entry class filenames 103fd8d1f79SSimon Glass """ 104fd8d1f79SSimon Glass glob_list = glob.glob(os.path.join(our_path, 'etype/*.py')) 105fd8d1f79SSimon Glass return set([os.path.splitext(os.path.basename(item))[0] 106fd8d1f79SSimon Glass for item in glob_list 107fd8d1f79SSimon Glass if include_testing or '_testing' not in item]) 108fd8d1f79SSimon Glass 109bf7fd50bSSimon Glassdef RunTestCoverage(): 110bf7fd50bSSimon Glass """Run the tests and check that we get 100% coverage""" 111fd8d1f79SSimon Glass glob_list = GetEntryModules(False) 11216d836cdSTom Rini all_set = set([os.path.splitext(os.path.basename(item))[0] 11316d836cdSTom Rini for item in glob_list if '_testing' not in item]) 114ff1fd6ccSSimon Glass test_util.RunTestCoverage('tools/binman/binman.py', None, 115ff1fd6ccSSimon Glass ['*test*', '*binman.py', 'tools/patman/*', 'tools/dtoc/*'], 116ff1fd6ccSSimon Glass options.build_dir, all_set) 117bf7fd50bSSimon Glass 118bf7fd50bSSimon Glassdef RunBinman(options, args): 119bf7fd50bSSimon Glass """Main entry point to binman once arguments are parsed 120bf7fd50bSSimon Glass 121bf7fd50bSSimon Glass Args: 122bf7fd50bSSimon Glass options: Command-line options 123bf7fd50bSSimon Glass args: Non-option arguments 124bf7fd50bSSimon Glass """ 125bf7fd50bSSimon Glass ret_code = 0 126bf7fd50bSSimon Glass 127bf7fd50bSSimon Glass # For testing: This enables full exception traces. 128bf7fd50bSSimon Glass #options.debug = True 129bf7fd50bSSimon Glass 130bf7fd50bSSimon Glass if not options.debug: 131bf7fd50bSSimon Glass sys.tracebacklimit = 0 132bf7fd50bSSimon Glass 133bf7fd50bSSimon Glass if options.test: 134*11ae93eeSSimon Glass ret_code = RunTests(options.debug, options.processes, args[1:]) 135bf7fd50bSSimon Glass 136bf7fd50bSSimon Glass elif options.test_coverage: 137bf7fd50bSSimon Glass RunTestCoverage() 138bf7fd50bSSimon Glass 139fd8d1f79SSimon Glass elif options.entry_docs: 140fd8d1f79SSimon Glass control.WriteEntryDocs(GetEntryModules()) 141bf7fd50bSSimon Glass 142bf7fd50bSSimon Glass else: 143bf7fd50bSSimon Glass try: 144bf7fd50bSSimon Glass ret_code = control.Binman(options, args) 145bf7fd50bSSimon Glass except Exception as e: 146bf7fd50bSSimon Glass print 'binman: %s' % e 147bf7fd50bSSimon Glass if options.debug: 148bf7fd50bSSimon Glass print 149bf7fd50bSSimon Glass traceback.print_exc() 150bf7fd50bSSimon Glass ret_code = 1 151bf7fd50bSSimon Glass return ret_code 152bf7fd50bSSimon Glass 153bf7fd50bSSimon Glass 154bf7fd50bSSimon Glassif __name__ == "__main__": 155bf7fd50bSSimon Glass (options, args) = cmdline.ParseArgs(sys.argv) 156bf7fd50bSSimon Glass ret_code = RunBinman(options, args) 157bf7fd50bSSimon Glass sys.exit(ret_code) 158