8736938d119f9dc4ee1449e8ea17f304d733b5a3
[platform/kernel/u-boot.git] / tools / binman / main.py
1 #!/usr/bin/env python3
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 from distutils.sysconfig import get_python_lib
13 import glob
14 import os
15 import site
16 import sys
17 import traceback
18 import unittest
19
20 # Bring in the patman and dtoc libraries (but don't override the first path
21 # in PYTHONPATH)
22 our_path = os.path.dirname(os.path.realpath(__file__))
23 for dirname in ['../patman', '../dtoc', '../concurrencytest', '..']:
24     sys.path.insert(2, os.path.realpath(os.path.join(our_path, dirname)))
25
26 # Bring in the libfdt module
27 sys.path.insert(2, 'scripts/dtc/pylibfdt')
28 sys.path.insert(2, os.path.join(our_path,
29                 '../../build-sandbox_spl/scripts/dtc/pylibfdt'))
30
31 # When running under python-coverage on Ubuntu 16.04, the dist-packages
32 # directories are dropped from the python path. Add them in so that we can find
33 # the elffile module. We could use site.getsitepackages() here but unfortunately
34 # that is not available in a virtualenv.
35 sys.path.append(get_python_lib())
36
37 from binman import cmdline
38 from binman import control
39 import test_util
40
41 def RunTests(debug, verbosity, processes, test_preserve_dirs, args, toolpath):
42     """Run the functional tests and any embedded doctests
43
44     Args:
45         debug: True to enable debugging, which shows a full stack trace on error
46         verbosity: Verbosity level to use
47         test_preserve_dirs: True to preserve the input directory used by tests
48             so that it can be examined afterwards (only useful for debugging
49             tests). If a single test is selected (in args[0]) it also preserves
50             the output directory for this test. Both directories are displayed
51             on the command line.
52         processes: Number of processes to use to run tests (None=same as #CPUs)
53         args: List of positional args provided to binman. This can hold a test
54             name to execute (as in 'binman test testSections', for example)
55         toolpath: List of paths to use for tools
56     """
57     from binman import cbfs_util_test
58     from binman import elf_test
59     from binman import entry_test
60     from binman import fdt_test
61     from binman import ftest
62     from binman import image_test
63     from binman import test
64     import doctest
65
66     result = unittest.TestResult()
67     test_name = args and args[0] or None
68
69     # Run the entry tests first ,since these need to be the first to import the
70     # 'entry' module.
71     test_util.RunTestSuites(
72         result, debug, verbosity, test_preserve_dirs, processes, test_name,
73         toolpath,
74         [entry_test.TestEntry, ftest.TestFunctional, fdt_test.TestFdt,
75          elf_test.TestElf, image_test.TestImage, cbfs_util_test.TestCbfs])
76
77     return test_util.ReportResult('binman', test_name, result)
78
79 def GetEntryModules(include_testing=True):
80     """Get a set of entry class implementations
81
82     Returns:
83         Set of paths to entry class filenames
84     """
85     glob_list = glob.glob(os.path.join(our_path, 'etype/*.py'))
86     return set([os.path.splitext(os.path.basename(item))[0]
87                 for item in glob_list
88                 if include_testing or '_testing' not in item])
89
90 def RunTestCoverage():
91     """Run the tests and check that we get 100% coverage"""
92     glob_list = GetEntryModules(False)
93     all_set = set([os.path.splitext(os.path.basename(item))[0]
94                    for item in glob_list if '_testing' not in item])
95     test_util.RunTestCoverage('tools/binman/binman', None,
96             ['*test*', '*main.py', 'tools/patman/*', 'tools/dtoc/*'],
97             args.build_dir, all_set)
98
99 def RunBinman(args):
100     """Main entry point to binman once arguments are parsed
101
102     Args:
103         args: Command line arguments Namespace object
104     """
105     ret_code = 0
106
107     if not args.debug:
108         sys.tracebacklimit = 0
109
110     if args.cmd == 'test':
111         if args.test_coverage:
112             RunTestCoverage()
113         else:
114             ret_code = RunTests(args.debug, args.verbosity, args.processes,
115                                 args.test_preserve_dirs, args.tests,
116                                 args.toolpath)
117
118     elif args.cmd == 'entry-docs':
119         control.WriteEntryDocs(GetEntryModules())
120
121     else:
122         try:
123             ret_code = control.Binman(args)
124         except Exception as e:
125             print('binman: %s' % e)
126             if args.debug:
127                 print()
128                 traceback.print_exc()
129             ret_code = 1
130     return ret_code
131
132
133 if __name__ == "__main__":
134     args = cmdline.ParseArgs(sys.argv[1:])
135
136     ret_code = RunBinman(args)
137     sys.exit(ret_code)