xref: /openbmc/u-boot/tools/binman/binman.py (revision c83c436d)
1#!/usr/bin/env python2
2# SPDX-License-Identifier: GPL-2.0+
3
4# Copyright (c) 2016 Google, Inc
5# Written by Simon Glass <sjg@chromium.org>
6#
7# Creates binary images from input files controlled by a description
8#
9
10"""See README for more information"""
11
12import glob
13import multiprocessing
14import os
15import sys
16import traceback
17import unittest
18
19# Bring in the patman and dtoc libraries
20our_path = os.path.dirname(os.path.realpath(__file__))
21for dirname in ['../patman', '../dtoc', '..', '../concurrencytest']:
22    sys.path.insert(0, os.path.join(our_path, dirname))
23
24# Bring in the libfdt module
25sys.path.insert(0, 'scripts/dtc/pylibfdt')
26sys.path.insert(0, os.path.join(our_path,
27                '../../build-sandbox_spl/scripts/dtc/pylibfdt'))
28
29import cmdline
30import command
31use_concurrent = True
32try:
33    from concurrencytest import ConcurrentTestSuite, fork_for_tests
34except:
35    use_concurrent = False
36import control
37import test_util
38
39def RunTests(debug, processes, args):
40    """Run the functional tests and any embedded doctests
41
42    Args:
43        debug: True to enable debugging, which shows a full stack trace on error
44        args: List of positional args provided to binman. This can hold a test
45            name to execute (as in 'binman -t testSections', for example)
46        processes: Number of processes to use to run tests (None=same as #CPUs)
47    """
48    import elf_test
49    import entry_test
50    import fdt_test
51    import ftest
52    import image_test
53    import test
54    import doctest
55
56    result = unittest.TestResult()
57    for module in []:
58        suite = doctest.DocTestSuite(module)
59        suite.run(result)
60
61    sys.argv = [sys.argv[0]]
62    if debug:
63        sys.argv.append('-D')
64    if debug:
65        sys.argv.append('-D')
66
67    # Run the entry tests first ,since these need to be the first to import the
68    # 'entry' module.
69    test_name = args and args[0] or None
70    suite = unittest.TestSuite()
71    loader = unittest.TestLoader()
72    for module in (entry_test.TestEntry, ftest.TestFunctional, fdt_test.TestFdt,
73                   elf_test.TestElf, image_test.TestImage):
74        if test_name:
75            try:
76                suite.addTests(loader.loadTestsFromName(test_name, module))
77            except AttributeError:
78                continue
79        else:
80            suite.addTests(loader.loadTestsFromTestCase(module))
81    if use_concurrent and processes != 1:
82        concurrent_suite = ConcurrentTestSuite(suite,
83                fork_for_tests(processes or multiprocessing.cpu_count()))
84        concurrent_suite.run(result)
85    else:
86        suite.run(result)
87
88    print result
89    for test, err in result.errors:
90        print test.id(), err
91    for test, err in result.failures:
92        print err, result.failures
93    if result.errors or result.failures:
94      print 'binman tests FAILED'
95      return 1
96    return 0
97
98def GetEntryModules(include_testing=True):
99    """Get a set of entry class implementations
100
101    Returns:
102        Set of paths to entry class filenames
103    """
104    glob_list = glob.glob(os.path.join(our_path, 'etype/*.py'))
105    return set([os.path.splitext(os.path.basename(item))[0]
106                for item in glob_list
107                if include_testing or '_testing' not in item])
108
109def RunTestCoverage():
110    """Run the tests and check that we get 100% coverage"""
111    glob_list = GetEntryModules(False)
112    all_set = set([os.path.splitext(os.path.basename(item))[0]
113                   for item in glob_list if '_testing' not in item])
114    test_util.RunTestCoverage('tools/binman/binman.py', None,
115            ['*test*', '*binman.py', 'tools/patman/*', 'tools/dtoc/*'],
116            options.build_dir, all_set)
117
118def RunBinman(options, args):
119    """Main entry point to binman once arguments are parsed
120
121    Args:
122        options: Command-line options
123        args: Non-option arguments
124    """
125    ret_code = 0
126
127    # For testing: This enables full exception traces.
128    #options.debug = True
129
130    if not options.debug:
131        sys.tracebacklimit = 0
132
133    if options.test:
134        ret_code = RunTests(options.debug, options.processes, args[1:])
135
136    elif options.test_coverage:
137        RunTestCoverage()
138
139    elif options.entry_docs:
140        control.WriteEntryDocs(GetEntryModules())
141
142    else:
143        try:
144            ret_code = control.Binman(options, args)
145        except Exception as e:
146            print 'binman: %s' % e
147            if options.debug:
148                print
149                traceback.print_exc()
150            ret_code = 1
151    return ret_code
152
153
154if __name__ == "__main__":
155    (options, args) = cmdline.ParseArgs(sys.argv)
156    ret_code = RunBinman(options, args)
157    sys.exit(ret_code)
158