Merge tag 'dm-9oct18' of git://git.denx.de/u-boot-dm
[platform/kernel/u-boot.git] / tools / binman / binman.py
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
12 import glob
13 import multiprocessing
14 import os
15 import sys
16 import traceback
17 import unittest
18
19 # Bring in the patman and dtoc libraries
20 our_path = os.path.dirname(os.path.realpath(__file__))
21 for dirname in ['../patman', '../dtoc', '..', '../concurrencytest']:
22     sys.path.insert(0, os.path.join(our_path, dirname))
23
24 # Bring in the libfdt module
25 sys.path.insert(0, 'scripts/dtc/pylibfdt')
26 sys.path.insert(0, os.path.join(our_path,
27                 '../../build-sandbox_spl/scripts/dtc/pylibfdt'))
28
29 import cmdline
30 import command
31 use_concurrent = True
32 try:
33     from concurrencytest import ConcurrentTestSuite, fork_for_tests
34 except:
35     use_concurrent = False
36 import control
37 import test_util
38
39 def 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
98 def 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
109 def 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
118 def 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
154 if __name__ == "__main__":
155     (options, args) = cmdline.ParseArgs(sys.argv)
156     ret_code = RunBinman(options, args)
157     sys.exit(ret_code)