xref: /openbmc/u-boot/tools/binman/binman.py (revision cf033e04)
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