]> git.sur5r.net Git - u-boot/blob - tools/binman/binman.py
binman: Switch to 'python-coverage'
[u-boot] / 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 os
14 import sys
15 import traceback
16 import unittest
17
18 # Bring in the patman and dtoc libraries
19 our_path = os.path.dirname(os.path.realpath(__file__))
20 for dirname in ['../patman', '../dtoc', '..']:
21     sys.path.insert(0, os.path.join(our_path, dirname))
22
23 # Bring in the libfdt module
24 sys.path.insert(0, 'scripts/dtc/pylibfdt')
25
26 import cmdline
27 import command
28 import control
29
30 def RunTests(debug, args):
31     """Run the functional tests and any embedded doctests
32
33     Args:
34         debug: True to enable debugging, which shows a full stack trace on error
35         args: List of positional args provided to binman. This can hold a test
36             name to execute (as in 'binman -t testSections', for example)
37     """
38     import elf_test
39     import entry_test
40     import fdt_test
41     import ftest
42     import image_test
43     import test
44     import doctest
45
46     result = unittest.TestResult()
47     for module in []:
48         suite = doctest.DocTestSuite(module)
49         suite.run(result)
50
51     sys.argv = [sys.argv[0]]
52     if debug:
53         sys.argv.append('-D')
54
55     # Run the entry tests first ,since these need to be the first to import the
56     # 'entry' module.
57     suite = unittest.TestLoader().loadTestsFromTestCase(entry_test.TestEntry)
58     suite.run(result)
59     test_name = args and args[0] or None
60     for module in (ftest.TestFunctional, fdt_test.TestFdt, elf_test.TestElf,
61                    image_test.TestImage):
62         if test_name:
63             try:
64                 suite = unittest.TestLoader().loadTestsFromName(args[0], module)
65             except AttributeError:
66                 continue
67         else:
68             suite = unittest.TestLoader().loadTestsFromTestCase(module)
69         suite.run(result)
70
71     print result
72     for test, err in result.errors:
73         print test.id(), err
74     for test, err in result.failures:
75         print err, result.failures
76     if result.errors or result.failures:
77       print 'binman tests FAILED'
78       return 1
79     return 0
80
81 def RunTestCoverage():
82     """Run the tests and check that we get 100% coverage"""
83     # This uses the build output from sandbox_spl to get _libfdt.so
84     cmd = ('PYTHONPATH=$PYTHONPATH:%s/sandbox_spl/tools python-coverage run '
85             '--include "tools/binman/*.py" --omit "*test*,*binman.py" '
86             'tools/binman/binman.py -t' % options.build_dir)
87     os.system(cmd)
88     stdout = command.Output('python-coverage', 'report')
89     lines = stdout.splitlines()
90
91     test_set= set([os.path.basename(line.split()[0])
92                      for line in lines if '/etype/' in line])
93     glob_list = glob.glob(os.path.join(our_path, 'etype/*.py'))
94     all_set = set([os.path.splitext(os.path.basename(item))[0]
95                    for item in glob_list if '_testing' not in item])
96     missing_list = all_set
97     missing_list.difference_update(test_set)
98     coverage = lines[-1].split(' ')[-1]
99     ok = True
100     if missing_list:
101         print 'Missing tests for %s' % (', '.join(missing_list))
102         print stdout
103         ok = False
104     if coverage != '100%':
105         print stdout
106         print "Type 'coverage html' to get a report in htmlcov/index.html"
107         print 'Coverage error: %s, but should be 100%%' % coverage
108         ok = False
109     if not ok:
110       raise ValueError('Test coverage failure')
111
112 def RunBinman(options, args):
113     """Main entry point to binman once arguments are parsed
114
115     Args:
116         options: Command-line options
117         args: Non-option arguments
118     """
119     ret_code = 0
120
121     # For testing: This enables full exception traces.
122     #options.debug = True
123
124     if not options.debug:
125         sys.tracebacklimit = 0
126
127     if options.test:
128         ret_code = RunTests(options.debug, args[1:])
129
130     elif options.test_coverage:
131         RunTestCoverage()
132
133     elif options.full_help:
134         pager = os.getenv('PAGER')
135         if not pager:
136             pager = 'more'
137         fname = os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])),
138                             'README')
139         command.Run(pager, fname)
140
141     else:
142         try:
143             ret_code = control.Binman(options, args)
144         except Exception as e:
145             print 'binman: %s' % e
146             if options.debug:
147                 print
148                 traceback.print_exc()
149             ret_code = 1
150     return ret_code
151
152
153 if __name__ == "__main__":
154     (options, args) = cmdline.ParseArgs(sys.argv)
155     ret_code = RunBinman(options, args)
156     sys.exit(ret_code)