]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - tools/buildman/func_test.py
buildman: Allow tests to have their own boards
[karo-tx-uboot.git] / tools / buildman / func_test.py
1 #
2 # Copyright (c) 2014 Google, Inc
3 #
4 # SPDX-License-Identifier:      GPL-2.0+
5 #
6
7 import os
8 import shutil
9 import sys
10 import tempfile
11 import unittest
12
13 import board
14 import bsettings
15 import cmdline
16 import command
17 import control
18 import gitutil
19 import terminal
20 import toolchain
21
22 settings_data = '''
23 # Buildman settings file
24
25 [toolchain]
26
27 [toolchain-alias]
28
29 [make-flags]
30 src=/home/sjg/c/src
31 chroot=/home/sjg/c/chroot
32 vboot=USE_STDINT=1 VBOOT_DEBUG=1 MAKEFLAGS_VBOOT=DEBUG=1 CFLAGS_EXTRA_VBOOT=-DUNROLL_LOOPS VBOOT_SOURCE=${src}/platform/vboot_reference
33 chromeos_coreboot=VBOOT=${chroot}/build/link/usr ${vboot}
34 chromeos_daisy=VBOOT=${chroot}/build/daisy/usr ${vboot}
35 chromeos_peach=VBOOT=${chroot}/build/peach_pit/usr ${vboot}
36 '''
37
38 boards = [
39     ['Active', 'arm', 'armv7', '', 'Tester', 'ARM Board 1', 'board0',  ''],
40     ['Active', 'arm', 'armv7', '', 'Tester', 'ARM Board 2', 'board1', ''],
41     ['Active', 'powerpc', 'powerpc', '', 'Tester', 'PowerPC board 1', 'board2', ''],
42     ['Active', 'powerpc', 'mpc5xx', '', 'Tester', 'PowerPC board 2', 'board3', ''],
43     ['Active', 'sandbox', 'sandbox', '', 'Tester', 'Sandbox board', 'board4', ''],
44 ]
45
46 class TestFunctional(unittest.TestCase):
47     """Functional test for buildman.
48
49     This aims to test from just below the invocation of buildman (parsing
50     of arguments) to 'make' and 'git' invocation. It is not a true
51     emd-to-end test, as it mocks git, make and the tool chain. But this
52     makes it easier to detect when the builder is doing the wrong thing,
53     since in many cases this test code will fail. For example, only a
54     very limited subset of 'git' arguments is supported - anything
55     unexpected will fail.
56     """
57     def setUp(self):
58         self._base_dir = tempfile.mkdtemp()
59         self._git_dir = os.path.join(self._base_dir, 'src')
60         self._buildman_pathname = sys.argv[0]
61         self._buildman_dir = os.path.dirname(sys.argv[0])
62         command.test_result = self._HandleCommand
63         self._toolchains = toolchain.Toolchains()
64         self._toolchains.Add('gcc', test=False)
65         bsettings.Setup(None)
66         bsettings.AddFile(settings_data)
67         self._boards = board.Boards()
68         for brd in boards:
69             self._boards.AddBoard(board.Board(*brd))
70
71     def tearDown(self):
72         shutil.rmtree(self._base_dir)
73
74     def _RunBuildman(self, *args):
75         return command.RunPipe([[self._buildman_pathname] + list(args)],
76                 capture=True, capture_stderr=True)
77
78     def _RunControl(self, *args):
79         sys.argv = [sys.argv[0]] + list(args)
80         options, args = cmdline.ParseArgs()
81         return control.DoBuildman(options, args, toolchains=self._toolchains,
82                 make_func=self._HandleMake, boards=self._boards)
83
84     def testFullHelp(self):
85         command.test_result = None
86         result = self._RunBuildman('-H')
87         help_file = os.path.join(self._buildman_dir, 'README')
88         self.assertEqual(len(result.stdout), os.path.getsize(help_file))
89         self.assertEqual(0, len(result.stderr))
90         self.assertEqual(0, result.return_code)
91
92     def testHelp(self):
93         command.test_result = None
94         result = self._RunBuildman('-h')
95         help_file = os.path.join(self._buildman_dir, 'README')
96         self.assertTrue(len(result.stdout) > 1000)
97         self.assertEqual(0, len(result.stderr))
98         self.assertEqual(0, result.return_code)
99
100     def testGitSetup(self):
101         """Test gitutils.Setup(), from outside the module itself"""
102         command.test_result = command.CommandResult(return_code=1)
103         gitutil.Setup()
104         self.assertEqual(gitutil.use_no_decorate, False)
105
106         command.test_result = command.CommandResult(return_code=0)
107         gitutil.Setup()
108         self.assertEqual(gitutil.use_no_decorate, True)
109
110     def _HandleCommandGitLog(self, args):
111         if '-n0' in args:
112             return command.CommandResult(return_code=0)
113
114         # Not handled, so abort
115         print 'git log', args
116         sys.exit(1)
117
118     def _HandleCommandGit(self, in_args):
119         """Handle execution of a git command
120
121         This uses a hacked-up parser.
122
123         Args:
124             in_args: Arguments after 'git' from the command line
125         """
126         git_args = []           # Top-level arguments to git itself
127         sub_cmd = None          # Git sub-command selected
128         args = []               # Arguments to the git sub-command
129         for arg in in_args:
130             if sub_cmd:
131                 args.append(arg)
132             elif arg[0] == '-':
133                 git_args.append(arg)
134             else:
135                 sub_cmd = arg
136         if sub_cmd == 'config':
137             return command.CommandResult(return_code=0)
138         elif sub_cmd == 'log':
139             return self._HandleCommandGitLog(args)
140
141         # Not handled, so abort
142         print 'git', git_args, sub_cmd, args
143         sys.exit(1)
144
145     def _HandleCommandNm(self, args):
146         return command.CommandResult(return_code=0)
147
148     def _HandleCommandObjdump(self, args):
149         return command.CommandResult(return_code=0)
150
151     def _HandleCommandSize(self, args):
152         return command.CommandResult(return_code=0)
153
154     def _HandleCommand(self, **kwargs):
155         """Handle a command execution.
156
157         The command is in kwargs['pipe-list'], as a list of pipes, each a
158         list of commands. The command should be emulated as required for
159         testing purposes.
160
161         Returns:
162             A CommandResult object
163         """
164         pipe_list = kwargs['pipe_list']
165         if len(pipe_list) != 1:
166             print 'invalid pipe', kwargs
167             sys.exit(1)
168         cmd = pipe_list[0][0]
169         args = pipe_list[0][1:]
170         if cmd == 'git':
171             return self._HandleCommandGit(args)
172         elif cmd == './scripts/show-gnu-make':
173             return command.CommandResult(return_code=0, stdout='make')
174         elif cmd == 'nm':
175             return self._HandleCommandNm(args)
176         elif cmd == 'objdump':
177             return self._HandleCommandObjdump(args)
178         elif cmd == 'size':
179             return self._HandleCommandSize(args)
180
181         # Not handled, so abort
182         print 'unknown command', kwargs
183         sys.exit(1)
184         return command.CommandResult(return_code=0)
185
186     def _HandleMake(self, commit, brd, stage, cwd, *args, **kwargs):
187         """Handle execution of 'make'
188
189         Args:
190             commit: Commit object that is being built
191             brd: Board object that is being built
192             stage: Stage that we are at (mrproper, config, build)
193             cwd: Directory where make should be run
194             args: Arguments to pass to make
195             kwargs: Arguments to pass to command.RunPipe()
196         """
197         if stage == 'mrproper':
198             return command.CommandResult(return_code=0)
199         elif stage == 'config':
200             return command.CommandResult(return_code=0,
201                     combined='Test configuration complete')
202         elif stage == 'build':
203             return command.CommandResult(return_code=0)
204
205         # Not handled, so abort
206         print 'make', stage
207         sys.exit(1)
208
209     def testNoBoards(self):
210         """Test that buildman aborts when there are no boards"""
211         self._boards = board.Boards()
212         with self.assertRaises(SystemExit):
213             self._RunControl()
214
215     def testCurrentSource(self):
216         """Very simple test to invoke buildman on the current source"""
217         self._RunControl()
218         lines = terminal.GetPrintTestLines()
219         self.assertTrue(lines[0].text.startswith('Building current source'))