blob: 9bfdd536985b2f13d8eb3314e480f8c47a4cb931 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001# SPDX-License-Identifier: GPL-2.0+
Simon Glassed098bb2014-09-05 19:00:13 -06002# Copyright (c) 2014 Google, Inc
3#
Simon Glassed098bb2014-09-05 19:00:13 -06004
5import os
6import shutil
7import sys
8import tempfile
9import unittest
10
Simon Glassf0d9c102020-04-17 18:09:02 -060011from buildman import board
12from buildman import bsettings
13from buildman import cmdline
14from buildman import control
15from buildman import toolchain
Simon Glassed098bb2014-09-05 19:00:13 -060016import command
Simon Glassed098bb2014-09-05 19:00:13 -060017import gitutil
18import terminal
19import toolchain
Simon Glassb6eb8cf2020-03-18 09:42:42 -060020import tools
Simon Glassed098bb2014-09-05 19:00:13 -060021
Simon Glass5e0441d2014-09-05 19:00:15 -060022settings_data = '''
23# Buildman settings file
24
25[toolchain]
26
27[toolchain-alias]
28
29[make-flags]
30src=/home/sjg/c/src
31chroot=/home/sjg/c/chroot
Masahiro Yamada72e545a2018-08-06 20:47:38 +090032vboot=VBOOT_DEBUG=1 MAKEFLAGS_VBOOT=DEBUG=1 CFLAGS_EXTRA_VBOOT=-DUNROLL_LOOPS VBOOT_SOURCE=${src}/platform/vboot_reference
Simon Glass5e0441d2014-09-05 19:00:15 -060033chromeos_coreboot=VBOOT=${chroot}/build/link/usr ${vboot}
34chromeos_daisy=VBOOT=${chroot}/build/daisy/usr ${vboot}
35chromeos_peach=VBOOT=${chroot}/build/peach_pit/usr ${vboot}
36'''
37
Simon Glasscbd36582014-09-05 19:00:16 -060038boards = [
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', ''],
Simon Glasscbd36582014-09-05 19:00:16 -060042 ['Active', 'sandbox', 'sandbox', '', 'Tester', 'Sandbox board', 'board4', ''],
43]
44
Simon Glass8e959562014-09-05 19:00:20 -060045commit_shortlog = """4aca821 patman: Avoid changing the order of tags
4639403bb patman: Use --no-pager' to stop git from forking a pager
47db6e6f2 patman: Remove the -a option
48f2ccf03 patman: Correct unit tests to run correctly
491d097f9 patman: Fix indentation in terminal.py
50d073747 patman: Support the 'reverse' option for 'git log
51"""
52
53commit_log = ["""commit 7f6b8315d18f683c5181d0c3694818c1b2a20dcd
54Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
55Date: Fri Aug 22 19:12:41 2014 +0900
56
57 buildman: refactor help message
58
59 "buildman [options]" is displayed by default.
60
61 Append the rest of help messages to parser.usage
62 instead of replacing it.
63
64 Besides, "-b <branch>" is not mandatory since commit fea5858e.
65 Drop it from the usage.
66
67 Signed-off-by: Masahiro Yamada <yamada.m@jp.panasonic.com>
68""",
69"""commit d0737479be6baf4db5e2cdbee123e96bc5ed0ba8
70Author: Simon Glass <sjg@chromium.org>
71Date: Thu Aug 14 16:48:25 2014 -0600
72
73 patman: Support the 'reverse' option for 'git log'
74
75 This option is currently not supported, but needs to be, for buildman to
76 operate as expected.
77
78 Series-changes: 7
79 - Add new patch to fix the 'reverse' bug
80
Simon Glass359b55a62014-09-05 19:00:23 -060081 Series-version: 8
Simon Glass8e959562014-09-05 19:00:20 -060082
83 Change-Id: I79078f792e8b390b8a1272a8023537821d45feda
84 Reported-by: York Sun <yorksun@freescale.com>
85 Signed-off-by: Simon Glass <sjg@chromium.org>
86
87""",
88"""commit 1d097f9ab487c5019152fd47bda126839f3bf9fc
89Author: Simon Glass <sjg@chromium.org>
90Date: Sat Aug 9 11:44:32 2014 -0600
91
92 patman: Fix indentation in terminal.py
93
94 This code came from a different project with 2-character indentation. Fix
95 it for U-Boot.
96
97 Series-changes: 6
98 - Add new patch to fix indentation in teminal.py
99
100 Change-Id: I5a74d2ebbb3cc12a665f5c725064009ac96e8a34
101 Signed-off-by: Simon Glass <sjg@chromium.org>
102
103""",
104"""commit f2ccf03869d1e152c836515a3ceb83cdfe04a105
105Author: Simon Glass <sjg@chromium.org>
106Date: Sat Aug 9 11:08:24 2014 -0600
107
108 patman: Correct unit tests to run correctly
109
110 It seems that doctest behaves differently now, and some of the unit tests
111 do not run. Adjust the tests to work correctly.
112
113 ./tools/patman/patman --test
114 <unittest.result.TestResult run=10 errors=0 failures=0>
115
116 Series-changes: 6
117 - Add new patch to fix patman unit tests
118
119 Change-Id: I3d2ca588f4933e1f9d6b1665a00e4ae58269ff3b
120
121""",
122"""commit db6e6f2f9331c5a37647d6668768d4a40b8b0d1c
123Author: Simon Glass <sjg@chromium.org>
124Date: Sat Aug 9 12:06:02 2014 -0600
125
126 patman: Remove the -a option
127
128 It seems that this is no longer needed, since checkpatch.pl will catch
129 whitespace problems in patches. Also the option is not widely used, so
130 it seems safe to just remove it.
131
132 Series-changes: 6
133 - Add new patch to remove patman's -a option
134
135 Suggested-by: Masahiro Yamada <yamada.m@jp.panasonic.com>
136 Change-Id: I5821a1c75154e532c46513486ca40b808de7e2cc
137
138""",
139"""commit 39403bb4f838153028a6f21ca30bf100f3791133
140Author: Simon Glass <sjg@chromium.org>
141Date: Thu Aug 14 21:50:52 2014 -0600
142
143 patman: Use --no-pager' to stop git from forking a pager
144
145""",
146"""commit 4aca821e27e97925c039e69fd37375b09c6f129c
147Author: Simon Glass <sjg@chromium.org>
148Date: Fri Aug 22 15:57:39 2014 -0600
149
150 patman: Avoid changing the order of tags
151
152 patman collects tags that it sees in the commit and places them nicely
153 sorted at the end of the patch. However, this is not really necessary and
154 in fact is apparently not desirable.
155
156 Series-changes: 9
157 - Add new patch to avoid changing the order of tags
158
Simon Glass359b55a62014-09-05 19:00:23 -0600159 Series-version: 9
160
Simon Glass8e959562014-09-05 19:00:20 -0600161 Suggested-by: Masahiro Yamada <yamada.m@jp.panasonic.com>
162 Change-Id: Ib1518588c1a189ad5c3198aae76f8654aed8d0db
163"""]
164
165TEST_BRANCH = '__testbranch'
166
Simon Glassed098bb2014-09-05 19:00:13 -0600167class TestFunctional(unittest.TestCase):
168 """Functional test for buildman.
169
170 This aims to test from just below the invocation of buildman (parsing
171 of arguments) to 'make' and 'git' invocation. It is not a true
172 emd-to-end test, as it mocks git, make and the tool chain. But this
173 makes it easier to detect when the builder is doing the wrong thing,
174 since in many cases this test code will fail. For example, only a
175 very limited subset of 'git' arguments is supported - anything
176 unexpected will fail.
177 """
178 def setUp(self):
179 self._base_dir = tempfile.mkdtemp()
Tom Rinie95eddc2019-10-07 17:17:36 -0400180 self._output_dir = tempfile.mkdtemp()
Simon Glassed098bb2014-09-05 19:00:13 -0600181 self._git_dir = os.path.join(self._base_dir, 'src')
182 self._buildman_pathname = sys.argv[0]
Simon Glass5d4a7872016-07-27 20:33:00 -0600183 self._buildman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
Simon Glassed098bb2014-09-05 19:00:13 -0600184 command.test_result = self._HandleCommand
Simon Glass8e959562014-09-05 19:00:20 -0600185 self.setupToolchains()
186 self._toolchains.Add('arm-gcc', test=False)
187 self._toolchains.Add('powerpc-gcc', test=False)
Simon Glass5e0441d2014-09-05 19:00:15 -0600188 bsettings.Setup(None)
189 bsettings.AddFile(settings_data)
Simon Glasscbd36582014-09-05 19:00:16 -0600190 self._boards = board.Boards()
191 for brd in boards:
192 self._boards.AddBoard(board.Board(*brd))
Simon Glassed098bb2014-09-05 19:00:13 -0600193
Simon Glass8e959562014-09-05 19:00:20 -0600194 # Directories where the source been cloned
195 self._clone_dirs = []
196 self._commits = len(commit_shortlog.splitlines()) + 1
197 self._total_builds = self._commits * len(boards)
198
199 # Number of calls to make
200 self._make_calls = 0
201
202 # Map of [board, commit] to error messages
203 self._error = {}
204
Simon Glass4aeceb92014-09-05 19:00:22 -0600205 self._test_branch = TEST_BRANCH
206
Simon Glass8e959562014-09-05 19:00:20 -0600207 # Avoid sending any output and clear all terminal output
208 terminal.SetPrintTestMode()
209 terminal.GetPrintTestLines()
210
Simon Glassed098bb2014-09-05 19:00:13 -0600211 def tearDown(self):
212 shutil.rmtree(self._base_dir)
Simon Glassb6eb8cf2020-03-18 09:42:42 -0600213 #shutil.rmtree(self._output_dir)
Simon Glassed098bb2014-09-05 19:00:13 -0600214
Simon Glass8e959562014-09-05 19:00:20 -0600215 def setupToolchains(self):
216 self._toolchains = toolchain.Toolchains()
217 self._toolchains.Add('gcc', test=False)
218
Simon Glassed098bb2014-09-05 19:00:13 -0600219 def _RunBuildman(self, *args):
220 return command.RunPipe([[self._buildman_pathname] + list(args)],
221 capture=True, capture_stderr=True)
222
Simon Glassb6eb8cf2020-03-18 09:42:42 -0600223 def _RunControl(self, *args, clean_dir=False, boards=None):
Simon Glassed098bb2014-09-05 19:00:13 -0600224 sys.argv = [sys.argv[0]] + list(args)
225 options, args = cmdline.ParseArgs()
Simon Glass8e959562014-09-05 19:00:20 -0600226 result = control.DoBuildman(options, args, toolchains=self._toolchains,
Simon Glassb6eb8cf2020-03-18 09:42:42 -0600227 make_func=self._HandleMake, boards=boards or self._boards,
228 clean_dir=clean_dir)
Simon Glass8e959562014-09-05 19:00:20 -0600229 self._builder = control.builder
230 return result
Simon Glassed098bb2014-09-05 19:00:13 -0600231
232 def testFullHelp(self):
233 command.test_result = None
234 result = self._RunBuildman('-H')
235 help_file = os.path.join(self._buildman_dir, 'README')
Tom Rinic3c0b6d2018-01-16 15:29:50 -0500236 # Remove possible extraneous strings
237 extra = '::::::::::::::\n' + help_file + '\n::::::::::::::\n'
238 gothelp = result.stdout.replace(extra, '')
239 self.assertEqual(len(gothelp), os.path.getsize(help_file))
Simon Glassed098bb2014-09-05 19:00:13 -0600240 self.assertEqual(0, len(result.stderr))
241 self.assertEqual(0, result.return_code)
242
243 def testHelp(self):
244 command.test_result = None
245 result = self._RunBuildman('-h')
246 help_file = os.path.join(self._buildman_dir, 'README')
247 self.assertTrue(len(result.stdout) > 1000)
248 self.assertEqual(0, len(result.stderr))
249 self.assertEqual(0, result.return_code)
250
251 def testGitSetup(self):
252 """Test gitutils.Setup(), from outside the module itself"""
253 command.test_result = command.CommandResult(return_code=1)
254 gitutil.Setup()
255 self.assertEqual(gitutil.use_no_decorate, False)
256
257 command.test_result = command.CommandResult(return_code=0)
258 gitutil.Setup()
259 self.assertEqual(gitutil.use_no_decorate, True)
260
261 def _HandleCommandGitLog(self, args):
Simon Glass642e9a62016-03-12 18:50:31 -0700262 if args[-1] == '--':
263 args = args[:-1]
Simon Glassed098bb2014-09-05 19:00:13 -0600264 if '-n0' in args:
265 return command.CommandResult(return_code=0)
Simon Glass4aeceb92014-09-05 19:00:22 -0600266 elif args[-1] == 'upstream/master..%s' % self._test_branch:
Simon Glass8e959562014-09-05 19:00:20 -0600267 return command.CommandResult(return_code=0, stdout=commit_shortlog)
268 elif args[:3] == ['--no-color', '--no-decorate', '--reverse']:
Simon Glass4aeceb92014-09-05 19:00:22 -0600269 if args[-1] == self._test_branch:
Simon Glass8e959562014-09-05 19:00:20 -0600270 count = int(args[3][2:])
271 return command.CommandResult(return_code=0,
272 stdout=''.join(commit_log[:count]))
Simon Glassed098bb2014-09-05 19:00:13 -0600273
274 # Not handled, so abort
Simon Glassc78ed662019-10-31 07:42:53 -0600275 print('git log', args)
Simon Glassed098bb2014-09-05 19:00:13 -0600276 sys.exit(1)
277
Simon Glass8e959562014-09-05 19:00:20 -0600278 def _HandleCommandGitConfig(self, args):
279 config = args[0]
280 if config == 'sendemail.aliasesfile':
281 return command.CommandResult(return_code=0)
282 elif config.startswith('branch.badbranch'):
283 return command.CommandResult(return_code=1)
Simon Glass4aeceb92014-09-05 19:00:22 -0600284 elif config == 'branch.%s.remote' % self._test_branch:
Simon Glass8e959562014-09-05 19:00:20 -0600285 return command.CommandResult(return_code=0, stdout='upstream\n')
Simon Glass4aeceb92014-09-05 19:00:22 -0600286 elif config == 'branch.%s.merge' % self._test_branch:
Simon Glass8e959562014-09-05 19:00:20 -0600287 return command.CommandResult(return_code=0,
288 stdout='refs/heads/master\n')
289
290 # Not handled, so abort
Simon Glassc78ed662019-10-31 07:42:53 -0600291 print('git config', args)
Simon Glass8e959562014-09-05 19:00:20 -0600292 sys.exit(1)
293
Simon Glassed098bb2014-09-05 19:00:13 -0600294 def _HandleCommandGit(self, in_args):
295 """Handle execution of a git command
296
297 This uses a hacked-up parser.
298
299 Args:
300 in_args: Arguments after 'git' from the command line
301 """
302 git_args = [] # Top-level arguments to git itself
303 sub_cmd = None # Git sub-command selected
304 args = [] # Arguments to the git sub-command
305 for arg in in_args:
306 if sub_cmd:
307 args.append(arg)
308 elif arg[0] == '-':
309 git_args.append(arg)
310 else:
Simon Glass8e959562014-09-05 19:00:20 -0600311 if git_args and git_args[-1] in ['--git-dir', '--work-tree']:
312 git_args.append(arg)
313 else:
314 sub_cmd = arg
Simon Glassed098bb2014-09-05 19:00:13 -0600315 if sub_cmd == 'config':
Simon Glass8e959562014-09-05 19:00:20 -0600316 return self._HandleCommandGitConfig(args)
Simon Glassed098bb2014-09-05 19:00:13 -0600317 elif sub_cmd == 'log':
318 return self._HandleCommandGitLog(args)
Simon Glass8e959562014-09-05 19:00:20 -0600319 elif sub_cmd == 'clone':
320 return command.CommandResult(return_code=0)
321 elif sub_cmd == 'checkout':
322 return command.CommandResult(return_code=0)
Simon Glassed098bb2014-09-05 19:00:13 -0600323
324 # Not handled, so abort
Simon Glassc78ed662019-10-31 07:42:53 -0600325 print('git', git_args, sub_cmd, args)
Simon Glassed098bb2014-09-05 19:00:13 -0600326 sys.exit(1)
327
328 def _HandleCommandNm(self, args):
329 return command.CommandResult(return_code=0)
330
331 def _HandleCommandObjdump(self, args):
332 return command.CommandResult(return_code=0)
333
Alex Kiernanf07ed232018-05-31 04:48:33 +0000334 def _HandleCommandObjcopy(self, args):
335 return command.CommandResult(return_code=0)
336
Simon Glassed098bb2014-09-05 19:00:13 -0600337 def _HandleCommandSize(self, args):
338 return command.CommandResult(return_code=0)
339
340 def _HandleCommand(self, **kwargs):
341 """Handle a command execution.
342
343 The command is in kwargs['pipe-list'], as a list of pipes, each a
344 list of commands. The command should be emulated as required for
345 testing purposes.
346
347 Returns:
348 A CommandResult object
349 """
350 pipe_list = kwargs['pipe_list']
Simon Glass8e959562014-09-05 19:00:20 -0600351 wc = False
Simon Glassed098bb2014-09-05 19:00:13 -0600352 if len(pipe_list) != 1:
Simon Glass8e959562014-09-05 19:00:20 -0600353 if pipe_list[1] == ['wc', '-l']:
354 wc = True
355 else:
Simon Glassc78ed662019-10-31 07:42:53 -0600356 print('invalid pipe', kwargs)
Simon Glass8e959562014-09-05 19:00:20 -0600357 sys.exit(1)
Simon Glassed098bb2014-09-05 19:00:13 -0600358 cmd = pipe_list[0][0]
359 args = pipe_list[0][1:]
Simon Glass8e959562014-09-05 19:00:20 -0600360 result = None
Simon Glassed098bb2014-09-05 19:00:13 -0600361 if cmd == 'git':
Simon Glass8e959562014-09-05 19:00:20 -0600362 result = self._HandleCommandGit(args)
Simon Glassed098bb2014-09-05 19:00:13 -0600363 elif cmd == './scripts/show-gnu-make':
364 return command.CommandResult(return_code=0, stdout='make')
Simon Glass8e959562014-09-05 19:00:20 -0600365 elif cmd.endswith('nm'):
Simon Glassed098bb2014-09-05 19:00:13 -0600366 return self._HandleCommandNm(args)
Simon Glass8e959562014-09-05 19:00:20 -0600367 elif cmd.endswith('objdump'):
Simon Glassed098bb2014-09-05 19:00:13 -0600368 return self._HandleCommandObjdump(args)
Alex Kiernanf07ed232018-05-31 04:48:33 +0000369 elif cmd.endswith('objcopy'):
370 return self._HandleCommandObjcopy(args)
Simon Glass8e959562014-09-05 19:00:20 -0600371 elif cmd.endswith( 'size'):
Simon Glassed098bb2014-09-05 19:00:13 -0600372 return self._HandleCommandSize(args)
373
Simon Glass8e959562014-09-05 19:00:20 -0600374 if not result:
375 # Not handled, so abort
Simon Glassc78ed662019-10-31 07:42:53 -0600376 print('unknown command', kwargs)
Simon Glass8e959562014-09-05 19:00:20 -0600377 sys.exit(1)
378
379 if wc:
380 result.stdout = len(result.stdout.splitlines())
381 return result
Simon Glassed098bb2014-09-05 19:00:13 -0600382
383 def _HandleMake(self, commit, brd, stage, cwd, *args, **kwargs):
384 """Handle execution of 'make'
385
386 Args:
387 commit: Commit object that is being built
388 brd: Board object that is being built
389 stage: Stage that we are at (mrproper, config, build)
390 cwd: Directory where make should be run
391 args: Arguments to pass to make
392 kwargs: Arguments to pass to command.RunPipe()
393 """
Simon Glass8e959562014-09-05 19:00:20 -0600394 self._make_calls += 1
Simon Glassed098bb2014-09-05 19:00:13 -0600395 if stage == 'mrproper':
396 return command.CommandResult(return_code=0)
397 elif stage == 'config':
398 return command.CommandResult(return_code=0,
399 combined='Test configuration complete')
400 elif stage == 'build':
Simon Glass8e959562014-09-05 19:00:20 -0600401 stderr = ''
Simon Glassb6eb8cf2020-03-18 09:42:42 -0600402 out_dir = ''
403 for arg in args:
404 if arg.startswith('O='):
405 out_dir = arg[2:]
406 fname = os.path.join(cwd or '', out_dir, 'u-boot')
407 tools.WriteFile(fname, b'U-Boot')
Simon Glass8e959562014-09-05 19:00:20 -0600408 if type(commit) is not str:
409 stderr = self._error.get((brd.target, commit.sequence))
410 if stderr:
411 return command.CommandResult(return_code=1, stderr=stderr)
Simon Glassed098bb2014-09-05 19:00:13 -0600412 return command.CommandResult(return_code=0)
413
414 # Not handled, so abort
Simon Glassc78ed662019-10-31 07:42:53 -0600415 print('make', stage)
Simon Glassed098bb2014-09-05 19:00:13 -0600416 sys.exit(1)
417
Simon Glass8e959562014-09-05 19:00:20 -0600418 # Example function to print output lines
419 def print_lines(self, lines):
Simon Glassc78ed662019-10-31 07:42:53 -0600420 print(len(lines))
Simon Glass8e959562014-09-05 19:00:20 -0600421 for line in lines:
Simon Glassc78ed662019-10-31 07:42:53 -0600422 print(line)
Simon Glass8e959562014-09-05 19:00:20 -0600423 #self.print_lines(terminal.GetPrintTestLines())
424
Simon Glasscbd36582014-09-05 19:00:16 -0600425 def testNoBoards(self):
426 """Test that buildman aborts when there are no boards"""
427 self._boards = board.Boards()
428 with self.assertRaises(SystemExit):
429 self._RunControl()
430
Simon Glassed098bb2014-09-05 19:00:13 -0600431 def testCurrentSource(self):
432 """Very simple test to invoke buildman on the current source"""
Simon Glass8e959562014-09-05 19:00:20 -0600433 self.setupToolchains();
Tom Rinie95eddc2019-10-07 17:17:36 -0400434 self._RunControl('-o', self._output_dir)
Simon Glassed098bb2014-09-05 19:00:13 -0600435 lines = terminal.GetPrintTestLines()
Simon Glass8e959562014-09-05 19:00:20 -0600436 self.assertIn('Building current source for %d boards' % len(boards),
437 lines[0].text)
438
439 def testBadBranch(self):
440 """Test that we can detect an invalid branch"""
441 with self.assertRaises(ValueError):
442 self._RunControl('-b', 'badbranch')
443
444 def testBadToolchain(self):
445 """Test that missing toolchains are detected"""
446 self.setupToolchains();
Tom Rinie95eddc2019-10-07 17:17:36 -0400447 ret_code = self._RunControl('-b', TEST_BRANCH, '-o', self._output_dir)
Simon Glass8e959562014-09-05 19:00:20 -0600448 lines = terminal.GetPrintTestLines()
449
450 # Buildman always builds the upstream commit as well
451 self.assertIn('Building %d commits for %d boards' %
452 (self._commits, len(boards)), lines[0].text)
453 self.assertEqual(self._builder.count, self._total_builds)
454
455 # Only sandbox should succeed, the others don't have toolchains
456 self.assertEqual(self._builder.fail,
457 self._total_builds - self._commits)
Simon Glasse4cd5062020-04-09 10:49:45 -0600458 self.assertEqual(ret_code, 100)
Simon Glass8e959562014-09-05 19:00:20 -0600459
460 for commit in range(self._commits):
461 for board in self._boards.GetList():
462 if board.arch != 'sandbox':
463 errfile = self._builder.GetErrFile(commit, board.target)
464 fd = open(errfile)
465 self.assertEqual(fd.readlines(),
466 ['No tool chain for %s\n' % board.arch])
467 fd.close()
468
469 def testBranch(self):
470 """Test building a branch with all toolchains present"""
Tom Rinie95eddc2019-10-07 17:17:36 -0400471 self._RunControl('-b', TEST_BRANCH, '-o', self._output_dir)
Simon Glass8e959562014-09-05 19:00:20 -0600472 self.assertEqual(self._builder.count, self._total_builds)
473 self.assertEqual(self._builder.fail, 0)
474
475 def testCount(self):
476 """Test building a specific number of commitst"""
Tom Rinie95eddc2019-10-07 17:17:36 -0400477 self._RunControl('-b', TEST_BRANCH, '-c2', '-o', self._output_dir)
Simon Glass8e959562014-09-05 19:00:20 -0600478 self.assertEqual(self._builder.count, 2 * len(boards))
479 self.assertEqual(self._builder.fail, 0)
Simon Glass6029af12020-04-09 15:08:51 -0600480 # Each board has a config, and then one make per commit
481 self.assertEqual(self._make_calls, len(boards) * (1 + 2))
Simon Glass8e959562014-09-05 19:00:20 -0600482
483 def testIncremental(self):
484 """Test building a branch twice - the second time should do nothing"""
Tom Rinie95eddc2019-10-07 17:17:36 -0400485 self._RunControl('-b', TEST_BRANCH, '-o', self._output_dir)
Simon Glass8e959562014-09-05 19:00:20 -0600486
487 # Each board has a mrproper, config, and then one make per commit
Simon Glass6029af12020-04-09 15:08:51 -0600488 self.assertEqual(self._make_calls, len(boards) * (self._commits + 1))
Simon Glass8e959562014-09-05 19:00:20 -0600489 self._make_calls = 0
Tom Rinie95eddc2019-10-07 17:17:36 -0400490 self._RunControl('-b', TEST_BRANCH, '-o', self._output_dir, clean_dir=False)
Simon Glass8e959562014-09-05 19:00:20 -0600491 self.assertEqual(self._make_calls, 0)
492 self.assertEqual(self._builder.count, self._total_builds)
493 self.assertEqual(self._builder.fail, 0)
494
495 def testForceBuild(self):
496 """The -f flag should force a rebuild"""
Tom Rinie95eddc2019-10-07 17:17:36 -0400497 self._RunControl('-b', TEST_BRANCH, '-o', self._output_dir)
Simon Glass8e959562014-09-05 19:00:20 -0600498 self._make_calls = 0
Tom Rinie95eddc2019-10-07 17:17:36 -0400499 self._RunControl('-b', TEST_BRANCH, '-f', '-o', self._output_dir, clean_dir=False)
Simon Glass6029af12020-04-09 15:08:51 -0600500 # Each board has a config and one make per commit
501 self.assertEqual(self._make_calls, len(boards) * (self._commits + 1))
Simon Glass8e959562014-09-05 19:00:20 -0600502
503 def testForceReconfigure(self):
504 """The -f flag should force a rebuild"""
Tom Rinie95eddc2019-10-07 17:17:36 -0400505 self._RunControl('-b', TEST_BRANCH, '-C', '-o', self._output_dir)
Simon Glass6029af12020-04-09 15:08:51 -0600506 # Each commit has a config and make
507 self.assertEqual(self._make_calls, len(boards) * self._commits * 2)
508
509 def testForceReconfigure(self):
510 """The -f flag should force a rebuild"""
511 self._RunControl('-b', TEST_BRANCH, '-C', '-o', self._output_dir)
512 # Each commit has a config and make
513 self.assertEqual(self._make_calls, len(boards) * self._commits * 2)
514
515 def testMrproper(self):
516 """The -f flag should force a rebuild"""
517 self._RunControl('-b', TEST_BRANCH, '-m', '-o', self._output_dir)
518 # Each board has a mkproper, config and then one make per commit
519 self.assertEqual(self._make_calls, len(boards) * (self._commits + 2))
Simon Glass8e959562014-09-05 19:00:20 -0600520
521 def testErrors(self):
522 """Test handling of build errors"""
523 self._error['board2', 1] = 'fred\n'
Tom Rinie95eddc2019-10-07 17:17:36 -0400524 self._RunControl('-b', TEST_BRANCH, '-o', self._output_dir)
Simon Glass8e959562014-09-05 19:00:20 -0600525 self.assertEqual(self._builder.count, self._total_builds)
526 self.assertEqual(self._builder.fail, 1)
527
528 # Remove the error. This should have no effect since the commit will
529 # not be rebuilt
530 del self._error['board2', 1]
531 self._make_calls = 0
Tom Rinie95eddc2019-10-07 17:17:36 -0400532 self._RunControl('-b', TEST_BRANCH, '-o', self._output_dir, clean_dir=False)
Simon Glass8e959562014-09-05 19:00:20 -0600533 self.assertEqual(self._builder.count, self._total_builds)
534 self.assertEqual(self._make_calls, 0)
535 self.assertEqual(self._builder.fail, 1)
536
537 # Now use the -F flag to force rebuild of the bad commit
Tom Rinie95eddc2019-10-07 17:17:36 -0400538 self._RunControl('-b', TEST_BRANCH, '-o', self._output_dir, '-F', clean_dir=False)
Simon Glass8e959562014-09-05 19:00:20 -0600539 self.assertEqual(self._builder.count, self._total_builds)
540 self.assertEqual(self._builder.fail, 0)
Simon Glass6029af12020-04-09 15:08:51 -0600541 self.assertEqual(self._make_calls, 2)
Simon Glass4aeceb92014-09-05 19:00:22 -0600542
543 def testBranchWithSlash(self):
544 """Test building a branch with a '/' in the name"""
545 self._test_branch = '/__dev/__testbranch'
546 self._RunControl('-b', self._test_branch, clean_dir=False)
547 self.assertEqual(self._builder.count, self._total_builds)
548 self.assertEqual(self._builder.fail, 0)
Lothar Waßmannce6df922018-04-08 05:14:11 -0600549
Simon Glassff48a212020-04-17 17:51:33 -0600550 def testEnvironment(self):
551 """Test that the done and environment files are written to out-env"""
552 self._RunControl('-o', self._output_dir)
553 board0_dir = os.path.join(self._output_dir, 'current', 'board0')
554 self.assertTrue(os.path.exists(os.path.join(board0_dir, 'done')))
555 self.assertTrue(os.path.exists(os.path.join(board0_dir, 'out-env')))
556
Simon Glassb6eb8cf2020-03-18 09:42:42 -0600557 def testWorkInOutput(self):
558 """Test the -w option which should write directly to the output dir"""
559 board_list = board.Boards()
560 board_list.AddBoard(board.Board(*boards[0]))
561 self._RunControl('-o', self._output_dir, '-w', clean_dir=False,
562 boards=board_list)
563 self.assertTrue(
564 os.path.exists(os.path.join(self._output_dir, 'u-boot')))
Simon Glasse3c85ab2020-04-17 17:51:34 -0600565 self.assertTrue(
566 os.path.exists(os.path.join(self._output_dir, 'done')))
567 self.assertTrue(
568 os.path.exists(os.path.join(self._output_dir, 'out-env')))
Simon Glassb6eb8cf2020-03-18 09:42:42 -0600569
570 def testWorkInOutputFail(self):
571 """Test the -w option failures"""
572 with self.assertRaises(SystemExit) as e:
573 self._RunControl('-o', self._output_dir, '-w', clean_dir=False)
574 self.assertIn("single board", str(e.exception))
575 self.assertFalse(
576 os.path.exists(os.path.join(self._output_dir, 'u-boot')))
577
578 board_list = board.Boards()
579 board_list.AddBoard(board.Board(*boards[0]))
580 with self.assertRaises(SystemExit) as e:
581 self._RunControl('-b', self._test_branch, '-o', self._output_dir,
582 '-w', clean_dir=False, boards=board_list)
583 self.assertIn("single commit", str(e.exception))
Simon Glassd9c98632020-04-17 17:51:32 -0600584
585 board_list = board.Boards()
586 board_list.AddBoard(board.Board(*boards[0]))
587 with self.assertRaises(SystemExit) as e:
588 self._RunControl('-w', clean_dir=False)
589 self.assertIn("specify -o", str(e.exception))