blob: c6997d1ee25b015b19f27ccf88c62cb20eb2b0ab [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001# SPDX-License-Identifier: GPL-2.0+
Simon Glassd4144e42014-09-05 19:00:13 -06002# Copyright (c) 2014 Google, Inc
3#
Simon Glassd4144e42014-09-05 19:00:13 -06004
5import os
6import shutil
7import sys
8import tempfile
9import unittest
10
Simon Glass0ede00f2020-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 Glassbf776672020-04-17 18:09:04 -060016from patman import command
17from patman import gitutil
18from patman import terminal
19from patman import tools
Simon Glassd4144e42014-09-05 19:00:13 -060020
Simon Glass8b985ee2014-09-05 19:00:15 -060021settings_data = '''
22# Buildman settings file
23
24[toolchain]
25
26[toolchain-alias]
27
28[make-flags]
29src=/home/sjg/c/src
30chroot=/home/sjg/c/chroot
Masahiro Yamada98655432018-08-06 20:47:38 +090031vboot=VBOOT_DEBUG=1 MAKEFLAGS_VBOOT=DEBUG=1 CFLAGS_EXTRA_VBOOT=-DUNROLL_LOOPS VBOOT_SOURCE=${src}/platform/vboot_reference
Simon Glass8b985ee2014-09-05 19:00:15 -060032chromeos_coreboot=VBOOT=${chroot}/build/link/usr ${vboot}
33chromeos_daisy=VBOOT=${chroot}/build/daisy/usr ${vboot}
34chromeos_peach=VBOOT=${chroot}/build/peach_pit/usr ${vboot}
35'''
36
Simon Glass823e60b2014-09-05 19:00:16 -060037boards = [
38 ['Active', 'arm', 'armv7', '', 'Tester', 'ARM Board 1', 'board0', ''],
39 ['Active', 'arm', 'armv7', '', 'Tester', 'ARM Board 2', 'board1', ''],
40 ['Active', 'powerpc', 'powerpc', '', 'Tester', 'PowerPC board 1', 'board2', ''],
Simon Glass823e60b2014-09-05 19:00:16 -060041 ['Active', 'sandbox', 'sandbox', '', 'Tester', 'Sandbox board', 'board4', ''],
42]
43
Simon Glassdfb7e932014-09-05 19:00:20 -060044commit_shortlog = """4aca821 patman: Avoid changing the order of tags
4539403bb patman: Use --no-pager' to stop git from forking a pager
46db6e6f2 patman: Remove the -a option
47f2ccf03 patman: Correct unit tests to run correctly
481d097f9 patman: Fix indentation in terminal.py
49d073747 patman: Support the 'reverse' option for 'git log
50"""
51
52commit_log = ["""commit 7f6b8315d18f683c5181d0c3694818c1b2a20dcd
53Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
54Date: Fri Aug 22 19:12:41 2014 +0900
55
56 buildman: refactor help message
57
58 "buildman [options]" is displayed by default.
59
60 Append the rest of help messages to parser.usage
61 instead of replacing it.
62
63 Besides, "-b <branch>" is not mandatory since commit fea5858e.
64 Drop it from the usage.
65
66 Signed-off-by: Masahiro Yamada <yamada.m@jp.panasonic.com>
67""",
68"""commit d0737479be6baf4db5e2cdbee123e96bc5ed0ba8
69Author: Simon Glass <sjg@chromium.org>
70Date: Thu Aug 14 16:48:25 2014 -0600
71
72 patman: Support the 'reverse' option for 'git log'
73
74 This option is currently not supported, but needs to be, for buildman to
75 operate as expected.
76
77 Series-changes: 7
78 - Add new patch to fix the 'reverse' bug
79
Simon Glass950a2312014-09-05 19:00:23 -060080 Series-version: 8
Simon Glassdfb7e932014-09-05 19:00:20 -060081
82 Change-Id: I79078f792e8b390b8a1272a8023537821d45feda
83 Reported-by: York Sun <yorksun@freescale.com>
84 Signed-off-by: Simon Glass <sjg@chromium.org>
85
86""",
87"""commit 1d097f9ab487c5019152fd47bda126839f3bf9fc
88Author: Simon Glass <sjg@chromium.org>
89Date: Sat Aug 9 11:44:32 2014 -0600
90
91 patman: Fix indentation in terminal.py
92
93 This code came from a different project with 2-character indentation. Fix
94 it for U-Boot.
95
96 Series-changes: 6
97 - Add new patch to fix indentation in teminal.py
98
99 Change-Id: I5a74d2ebbb3cc12a665f5c725064009ac96e8a34
100 Signed-off-by: Simon Glass <sjg@chromium.org>
101
102""",
103"""commit f2ccf03869d1e152c836515a3ceb83cdfe04a105
104Author: Simon Glass <sjg@chromium.org>
105Date: Sat Aug 9 11:08:24 2014 -0600
106
107 patman: Correct unit tests to run correctly
108
109 It seems that doctest behaves differently now, and some of the unit tests
110 do not run. Adjust the tests to work correctly.
111
112 ./tools/patman/patman --test
113 <unittest.result.TestResult run=10 errors=0 failures=0>
114
115 Series-changes: 6
116 - Add new patch to fix patman unit tests
117
118 Change-Id: I3d2ca588f4933e1f9d6b1665a00e4ae58269ff3b
119
120""",
121"""commit db6e6f2f9331c5a37647d6668768d4a40b8b0d1c
122Author: Simon Glass <sjg@chromium.org>
123Date: Sat Aug 9 12:06:02 2014 -0600
124
125 patman: Remove the -a option
126
127 It seems that this is no longer needed, since checkpatch.pl will catch
128 whitespace problems in patches. Also the option is not widely used, so
129 it seems safe to just remove it.
130
131 Series-changes: 6
132 - Add new patch to remove patman's -a option
133
134 Suggested-by: Masahiro Yamada <yamada.m@jp.panasonic.com>
135 Change-Id: I5821a1c75154e532c46513486ca40b808de7e2cc
136
137""",
138"""commit 39403bb4f838153028a6f21ca30bf100f3791133
139Author: Simon Glass <sjg@chromium.org>
140Date: Thu Aug 14 21:50:52 2014 -0600
141
142 patman: Use --no-pager' to stop git from forking a pager
143
144""",
145"""commit 4aca821e27e97925c039e69fd37375b09c6f129c
146Author: Simon Glass <sjg@chromium.org>
147Date: Fri Aug 22 15:57:39 2014 -0600
148
149 patman: Avoid changing the order of tags
150
151 patman collects tags that it sees in the commit and places them nicely
152 sorted at the end of the patch. However, this is not really necessary and
153 in fact is apparently not desirable.
154
155 Series-changes: 9
156 - Add new patch to avoid changing the order of tags
157
Simon Glass950a2312014-09-05 19:00:23 -0600158 Series-version: 9
159
Simon Glassdfb7e932014-09-05 19:00:20 -0600160 Suggested-by: Masahiro Yamada <yamada.m@jp.panasonic.com>
161 Change-Id: Ib1518588c1a189ad5c3198aae76f8654aed8d0db
162"""]
163
164TEST_BRANCH = '__testbranch'
165
Simon Glassd4144e42014-09-05 19:00:13 -0600166class TestFunctional(unittest.TestCase):
167 """Functional test for buildman.
168
169 This aims to test from just below the invocation of buildman (parsing
170 of arguments) to 'make' and 'git' invocation. It is not a true
171 emd-to-end test, as it mocks git, make and the tool chain. But this
172 makes it easier to detect when the builder is doing the wrong thing,
173 since in many cases this test code will fail. For example, only a
174 very limited subset of 'git' arguments is supported - anything
175 unexpected will fail.
176 """
177 def setUp(self):
178 self._base_dir = tempfile.mkdtemp()
Tom Riniaae62582019-10-07 17:17:36 -0400179 self._output_dir = tempfile.mkdtemp()
Simon Glassd4144e42014-09-05 19:00:13 -0600180 self._git_dir = os.path.join(self._base_dir, 'src')
181 self._buildman_pathname = sys.argv[0]
Simon Glassbd6f5d92016-07-27 20:33:00 -0600182 self._buildman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
Simon Glassd4144e42014-09-05 19:00:13 -0600183 command.test_result = self._HandleCommand
Simon Glassdfb7e932014-09-05 19:00:20 -0600184 self.setupToolchains()
185 self._toolchains.Add('arm-gcc', test=False)
186 self._toolchains.Add('powerpc-gcc', test=False)
Simon Glass8b985ee2014-09-05 19:00:15 -0600187 bsettings.Setup(None)
188 bsettings.AddFile(settings_data)
Simon Glass823e60b2014-09-05 19:00:16 -0600189 self._boards = board.Boards()
190 for brd in boards:
191 self._boards.AddBoard(board.Board(*brd))
Simon Glassd4144e42014-09-05 19:00:13 -0600192
Simon Glassdfb7e932014-09-05 19:00:20 -0600193 # Directories where the source been cloned
194 self._clone_dirs = []
195 self._commits = len(commit_shortlog.splitlines()) + 1
196 self._total_builds = self._commits * len(boards)
197
198 # Number of calls to make
199 self._make_calls = 0
200
201 # Map of [board, commit] to error messages
202 self._error = {}
203
Simon Glassf7582ce2014-09-05 19:00:22 -0600204 self._test_branch = TEST_BRANCH
205
Simon Glassdfb7e932014-09-05 19:00:20 -0600206 # Avoid sending any output and clear all terminal output
207 terminal.SetPrintTestMode()
208 terminal.GetPrintTestLines()
209
Simon Glassd4144e42014-09-05 19:00:13 -0600210 def tearDown(self):
211 shutil.rmtree(self._base_dir)
Simon Glassd829f122020-03-18 09:42:42 -0600212 #shutil.rmtree(self._output_dir)
Simon Glassd4144e42014-09-05 19:00:13 -0600213
Simon Glassdfb7e932014-09-05 19:00:20 -0600214 def setupToolchains(self):
215 self._toolchains = toolchain.Toolchains()
216 self._toolchains.Add('gcc', test=False)
217
Simon Glassd4144e42014-09-05 19:00:13 -0600218 def _RunBuildman(self, *args):
219 return command.RunPipe([[self._buildman_pathname] + list(args)],
220 capture=True, capture_stderr=True)
221
Simon Glass24993312021-04-11 16:27:25 +1200222 """Run buildman
223
224 Args:
225 args: List of arguments to pass
226 boards:
227 clean_dir: Used for tests only, indicates that the existing output_dir
228 should be removed before starting the build
229
230 Returns:
231 result code from buildman
232 """
Simon Glassd4144e42014-09-05 19:00:13 -0600233 sys.argv = [sys.argv[0]] + list(args)
234 options, args = cmdline.ParseArgs()
Simon Glassdfb7e932014-09-05 19:00:20 -0600235 result = control.DoBuildman(options, args, toolchains=self._toolchains,
Simon Glassd829f122020-03-18 09:42:42 -0600236 make_func=self._HandleMake, boards=boards or self._boards,
Simon Glassdfb7e932014-09-05 19:00:20 -0600237 self._builder = control.builder
238 return result
Simon Glassd4144e42014-09-05 19:00:13 -0600239
240 def testFullHelp(self):
241 command.test_result = None
242 result = self._RunBuildman('-H')
243 help_file = os.path.join(self._buildman_dir, 'README')
Tom Rini3759df02018-01-16 15:29:50 -0500244 # Remove possible extraneous strings
245 extra = '::::::::::::::\n' + help_file + '\n::::::::::::::\n'
246 gothelp = result.stdout.replace(extra, '')
247 self.assertEqual(len(gothelp), os.path.getsize(help_file))
Simon Glassd4144e42014-09-05 19:00:13 -0600248 self.assertEqual(0, len(result.stderr))
249 self.assertEqual(0, result.return_code)
250
251 def testHelp(self):
252 command.test_result = None
253 result = self._RunBuildman('-h')
254 help_file = os.path.join(self._buildman_dir, 'README')
255 self.assertTrue(len(result.stdout) > 1000)
256 self.assertEqual(0, len(result.stderr))
257 self.assertEqual(0, result.return_code)
258
259 def testGitSetup(self):
260 """Test gitutils.Setup(), from outside the module itself"""
261 command.test_result = command.CommandResult(return_code=1)
262 gitutil.Setup()
263 self.assertEqual(gitutil.use_no_decorate, False)
264
265 command.test_result = command.CommandResult(return_code=0)
266 gitutil.Setup()
267 self.assertEqual(gitutil.use_no_decorate, True)
268
269 def _HandleCommandGitLog(self, args):
Simon Glassd4c85722016-03-12 18:50:31 -0700270 if args[-1] == '--':
271 args = args[:-1]
Simon Glassd4144e42014-09-05 19:00:13 -0600272 if '-n0' in args:
273 return command.CommandResult(return_code=0)
Simon Glassf7582ce2014-09-05 19:00:22 -0600274 elif args[-1] == 'upstream/master..%s' % self._test_branch:
Simon Glassdfb7e932014-09-05 19:00:20 -0600275 return command.CommandResult(return_code=0, stdout=commit_shortlog)
276 elif args[:3] == ['--no-color', '--no-decorate', '--reverse']:
Simon Glassf7582ce2014-09-05 19:00:22 -0600277 if args[-1] == self._test_branch:
Simon Glassdfb7e932014-09-05 19:00:20 -0600278 count = int(args[3][2:])
279 return command.CommandResult(return_code=0,
280 stdout=''.join(commit_log[:count]))
Simon Glassd4144e42014-09-05 19:00:13 -0600281
282 # Not handled, so abort
Simon Glassc05aa032019-10-31 07:42:53 -0600283 print('git log', args)
Simon Glassd4144e42014-09-05 19:00:13 -0600284 sys.exit(1)
285
Simon Glassdfb7e932014-09-05 19:00:20 -0600286 def _HandleCommandGitConfig(self, args):
287 config = args[0]
288 if config == 'sendemail.aliasesfile':
289 return command.CommandResult(return_code=0)
290 elif config.startswith('branch.badbranch'):
291 return command.CommandResult(return_code=1)
Simon Glassf7582ce2014-09-05 19:00:22 -0600292 elif config == 'branch.%s.remote' % self._test_branch:
Simon Glassdfb7e932014-09-05 19:00:20 -0600293 return command.CommandResult(return_code=0, stdout='upstream\n')
Simon Glassf7582ce2014-09-05 19:00:22 -0600294 elif config == 'branch.%s.merge' % self._test_branch:
Simon Glassdfb7e932014-09-05 19:00:20 -0600295 return command.CommandResult(return_code=0,
296 stdout='refs/heads/master\n')
297
298 # Not handled, so abort
Simon Glassc05aa032019-10-31 07:42:53 -0600299 print('git config', args)
Simon Glassdfb7e932014-09-05 19:00:20 -0600300 sys.exit(1)
301
Simon Glassd4144e42014-09-05 19:00:13 -0600302 def _HandleCommandGit(self, in_args):
303 """Handle execution of a git command
304
305 This uses a hacked-up parser.
306
307 Args:
308 in_args: Arguments after 'git' from the command line
309 """
310 git_args = [] # Top-level arguments to git itself
311 sub_cmd = None # Git sub-command selected
312 args = [] # Arguments to the git sub-command
313 for arg in in_args:
314 if sub_cmd:
315 args.append(arg)
316 elif arg[0] == '-':
317 git_args.append(arg)
318 else:
Simon Glassdfb7e932014-09-05 19:00:20 -0600319 if git_args and git_args[-1] in ['--git-dir', '--work-tree']:
320 git_args.append(arg)
321 else:
322 sub_cmd = arg
Simon Glassd4144e42014-09-05 19:00:13 -0600323 if sub_cmd == 'config':
Simon Glassdfb7e932014-09-05 19:00:20 -0600324 return self._HandleCommandGitConfig(args)
Simon Glassd4144e42014-09-05 19:00:13 -0600325 elif sub_cmd == 'log':
326 return self._HandleCommandGitLog(args)
Simon Glassdfb7e932014-09-05 19:00:20 -0600327 elif sub_cmd == 'clone':
328 return command.CommandResult(return_code=0)
329 elif sub_cmd == 'checkout':
330 return command.CommandResult(return_code=0)
Alper Nebi Yasak76de29f2020-09-03 15:51:03 +0300331 elif sub_cmd == 'worktree':
332 return command.CommandResult(return_code=0)
Simon Glassd4144e42014-09-05 19:00:13 -0600333
334 # Not handled, so abort
Simon Glassc05aa032019-10-31 07:42:53 -0600335 print('git', git_args, sub_cmd, args)
Simon Glassd4144e42014-09-05 19:00:13 -0600336 sys.exit(1)
337
338 def _HandleCommandNm(self, args):
339 return command.CommandResult(return_code=0)
340
341 def _HandleCommandObjdump(self, args):
342 return command.CommandResult(return_code=0)
343
Alex Kiernan0ddc5102018-05-31 04:48:33 +0000344 def _HandleCommandObjcopy(self, args):
345 return command.CommandResult(return_code=0)
346
Simon Glassd4144e42014-09-05 19:00:13 -0600347 def _HandleCommandSize(self, args):
348 return command.CommandResult(return_code=0)
349
350 def _HandleCommand(self, **kwargs):
351 """Handle a command execution.
352
353 The command is in kwargs['pipe-list'], as a list of pipes, each a
354 list of commands. The command should be emulated as required for
355 testing purposes.
356
357 Returns:
358 A CommandResult object
359 """
360 pipe_list = kwargs['pipe_list']
Simon Glassdfb7e932014-09-05 19:00:20 -0600361 wc = False
Simon Glassd4144e42014-09-05 19:00:13 -0600362 if len(pipe_list) != 1:
Simon Glassdfb7e932014-09-05 19:00:20 -0600363 if pipe_list[1] == ['wc', '-l']:
364 wc = True
365 else:
Simon Glassc05aa032019-10-31 07:42:53 -0600366 print('invalid pipe', kwargs)
Simon Glassdfb7e932014-09-05 19:00:20 -0600367 sys.exit(1)
Simon Glassd4144e42014-09-05 19:00:13 -0600368 cmd = pipe_list[0][0]
369 args = pipe_list[0][1:]
Simon Glassdfb7e932014-09-05 19:00:20 -0600370 result = None
Simon Glassd4144e42014-09-05 19:00:13 -0600371 if cmd == 'git':
Simon Glassdfb7e932014-09-05 19:00:20 -0600372 result = self._HandleCommandGit(args)
Simon Glassd4144e42014-09-05 19:00:13 -0600373 elif cmd == './scripts/show-gnu-make':
374 return command.CommandResult(return_code=0, stdout='make')
Simon Glassdfb7e932014-09-05 19:00:20 -0600375 elif cmd.endswith('nm'):
Simon Glassd4144e42014-09-05 19:00:13 -0600376 return self._HandleCommandNm(args)
Simon Glassdfb7e932014-09-05 19:00:20 -0600377 elif cmd.endswith('objdump'):
Simon Glassd4144e42014-09-05 19:00:13 -0600378 return self._HandleCommandObjdump(args)
Alex Kiernan0ddc5102018-05-31 04:48:33 +0000379 elif cmd.endswith('objcopy'):
380 return self._HandleCommandObjcopy(args)
Simon Glassdfb7e932014-09-05 19:00:20 -0600381 elif cmd.endswith( 'size'):
Simon Glassd4144e42014-09-05 19:00:13 -0600382 return self._HandleCommandSize(args)
383
Simon Glassdfb7e932014-09-05 19:00:20 -0600384 if not result:
385 # Not handled, so abort
Simon Glassc05aa032019-10-31 07:42:53 -0600386 print('unknown command', kwargs)
Simon Glassdfb7e932014-09-05 19:00:20 -0600387 sys.exit(1)
388
389 if wc:
390 result.stdout = len(result.stdout.splitlines())
391 return result
Simon Glassd4144e42014-09-05 19:00:13 -0600392
393 def _HandleMake(self, commit, brd, stage, cwd, *args, **kwargs):
394 """Handle execution of 'make'
395
396 Args:
397 commit: Commit object that is being built
398 brd: Board object that is being built
399 stage: Stage that we are at (mrproper, config, build)
400 cwd: Directory where make should be run
401 args: Arguments to pass to make
402 kwargs: Arguments to pass to command.RunPipe()
403 """
Simon Glassdfb7e932014-09-05 19:00:20 -0600404 self._make_calls += 1
Simon Glassd4144e42014-09-05 19:00:13 -0600405 if stage == 'mrproper':
406 return command.CommandResult(return_code=0)
407 elif stage == 'config':
408 return command.CommandResult(return_code=0,
409 combined='Test configuration complete')
410 elif stage == 'build':
Simon Glassdfb7e932014-09-05 19:00:20 -0600411 stderr = ''
Simon Glassd829f122020-03-18 09:42:42 -0600412 out_dir = ''
413 for arg in args:
414 if arg.startswith('O='):
415 out_dir = arg[2:]
416 fname = os.path.join(cwd or '', out_dir, 'u-boot')
417 tools.WriteFile(fname, b'U-Boot')
Simon Glassdfb7e932014-09-05 19:00:20 -0600418 if type(commit) is not str:
419 stderr = self._error.get((brd.target, commit.sequence))
420 if stderr:
421 return command.CommandResult(return_code=1, stderr=stderr)
Simon Glassd4144e42014-09-05 19:00:13 -0600422 return command.CommandResult(return_code=0)
423
424 # Not handled, so abort
Simon Glassc05aa032019-10-31 07:42:53 -0600425 print('make', stage)
Simon Glassd4144e42014-09-05 19:00:13 -0600426 sys.exit(1)
427
Simon Glassdfb7e932014-09-05 19:00:20 -0600428 # Example function to print output lines
429 def print_lines(self, lines):
Simon Glassc05aa032019-10-31 07:42:53 -0600430 print(len(lines))
Simon Glassdfb7e932014-09-05 19:00:20 -0600431 for line in lines:
Simon Glassc05aa032019-10-31 07:42:53 -0600432 print(line)
Simon Glassdfb7e932014-09-05 19:00:20 -0600433 #self.print_lines(terminal.GetPrintTestLines())
434
Simon Glass823e60b2014-09-05 19:00:16 -0600435 def testNoBoards(self):
436 """Test that buildman aborts when there are no boards"""
437 self._boards = board.Boards()
438 with self.assertRaises(SystemExit):
439 self._RunControl()
440
Simon Glassd4144e42014-09-05 19:00:13 -0600441 def testCurrentSource(self):
442 """Very simple test to invoke buildman on the current source"""
Simon Glassdfb7e932014-09-05 19:00:20 -0600443 self.setupToolchains();
Tom Riniaae62582019-10-07 17:17:36 -0400444 self._RunControl('-o', self._output_dir)
Simon Glassd4144e42014-09-05 19:00:13 -0600445 lines = terminal.GetPrintTestLines()
Simon Glassdfb7e932014-09-05 19:00:20 -0600446 self.assertIn('Building current source for %d boards' % len(boards),
447 lines[0].text)
448
449 def testBadBranch(self):
450 """Test that we can detect an invalid branch"""
451 with self.assertRaises(ValueError):
452 self._RunControl('-b', 'badbranch')
453
454 def testBadToolchain(self):
455 """Test that missing toolchains are detected"""
456 self.setupToolchains();
Tom Riniaae62582019-10-07 17:17:36 -0400457 ret_code = self._RunControl('-b', TEST_BRANCH, '-o', self._output_dir)
Simon Glassdfb7e932014-09-05 19:00:20 -0600458 lines = terminal.GetPrintTestLines()
459
460 # Buildman always builds the upstream commit as well
461 self.assertIn('Building %d commits for %d boards' %
462 (self._commits, len(boards)), lines[0].text)
463 self.assertEqual(self._builder.count, self._total_builds)
464
465 # Only sandbox should succeed, the others don't have toolchains
466 self.assertEqual(self._builder.fail,
467 self._total_builds - self._commits)
Simon Glassb1e5e6d2020-04-09 10:49:45 -0600468 self.assertEqual(ret_code, 100)
Simon Glassdfb7e932014-09-05 19:00:20 -0600469
470 for commit in range(self._commits):
471 for board in self._boards.GetList():
472 if board.arch != 'sandbox':
473 errfile = self._builder.GetErrFile(commit, board.target)
474 fd = open(errfile)
475 self.assertEqual(fd.readlines(),
476 ['No tool chain for %s\n' % board.arch])
477 fd.close()
478
479 def testBranch(self):
480 """Test building a branch with all toolchains present"""
Tom Riniaae62582019-10-07 17:17:36 -0400481 self._RunControl('-b', TEST_BRANCH, '-o', self._output_dir)
Simon Glassdfb7e932014-09-05 19:00:20 -0600482 self.assertEqual(self._builder.count, self._total_builds)
483 self.assertEqual(self._builder.fail, 0)
484
485 def testCount(self):
486 """Test building a specific number of commitst"""
Tom Riniaae62582019-10-07 17:17:36 -0400487 self._RunControl('-b', TEST_BRANCH, '-c2', '-o', self._output_dir)
Simon Glassdfb7e932014-09-05 19:00:20 -0600488 self.assertEqual(self._builder.count, 2 * len(boards))
489 self.assertEqual(self._builder.fail, 0)
Simon Glasseb70a2c2020-04-09 15:08:51 -0600490 # Each board has a config, and then one make per commit
491 self.assertEqual(self._make_calls, len(boards) * (1 + 2))
Simon Glassdfb7e932014-09-05 19:00:20 -0600492
493 def testIncremental(self):
494 """Test building a branch twice - the second time should do nothing"""
Tom Riniaae62582019-10-07 17:17:36 -0400495 self._RunControl('-b', TEST_BRANCH, '-o', self._output_dir)
Simon Glassdfb7e932014-09-05 19:00:20 -0600496
497 # Each board has a mrproper, config, and then one make per commit
Simon Glasseb70a2c2020-04-09 15:08:51 -0600498 self.assertEqual(self._make_calls, len(boards) * (self._commits + 1))
Simon Glassdfb7e932014-09-05 19:00:20 -0600499 self._make_calls = 0
Tom Riniaae62582019-10-07 17:17:36 -0400500 self._RunControl('-b', TEST_BRANCH, '-o', self._output_dir, clean_dir=False)
Simon Glassdfb7e932014-09-05 19:00:20 -0600501 self.assertEqual(self._make_calls, 0)
502 self.assertEqual(self._builder.count, self._total_builds)
503 self.assertEqual(self._builder.fail, 0)
504
505 def testForceBuild(self):
506 """The -f flag should force a rebuild"""
Tom Riniaae62582019-10-07 17:17:36 -0400507 self._RunControl('-b', TEST_BRANCH, '-o', self._output_dir)
Simon Glassdfb7e932014-09-05 19:00:20 -0600508 self._make_calls = 0
Tom Riniaae62582019-10-07 17:17:36 -0400509 self._RunControl('-b', TEST_BRANCH, '-f', '-o', self._output_dir, clean_dir=False)
Simon Glasseb70a2c2020-04-09 15:08:51 -0600510 # Each board has a config and one make per commit
511 self.assertEqual(self._make_calls, len(boards) * (self._commits + 1))
Simon Glassdfb7e932014-09-05 19:00:20 -0600512
513 def testForceReconfigure(self):
514 """The -f flag should force a rebuild"""
Tom Riniaae62582019-10-07 17:17:36 -0400515 self._RunControl('-b', TEST_BRANCH, '-C', '-o', self._output_dir)
Simon Glasseb70a2c2020-04-09 15:08:51 -0600516 # Each commit has a config and make
517 self.assertEqual(self._make_calls, len(boards) * self._commits * 2)
518
519 def testForceReconfigure(self):
520 """The -f flag should force a rebuild"""
521 self._RunControl('-b', TEST_BRANCH, '-C', '-o', self._output_dir)
522 # Each commit has a config and make
523 self.assertEqual(self._make_calls, len(boards) * self._commits * 2)
524
525 def testMrproper(self):
526 """The -f flag should force a rebuild"""
527 self._RunControl('-b', TEST_BRANCH, '-m', '-o', self._output_dir)
528 # Each board has a mkproper, config and then one make per commit
529 self.assertEqual(self._make_calls, len(boards) * (self._commits + 2))
Simon Glassdfb7e932014-09-05 19:00:20 -0600530
531 def testErrors(self):
532 """Test handling of build errors"""
533 self._error['board2', 1] = 'fred\n'
Tom Riniaae62582019-10-07 17:17:36 -0400534 self._RunControl('-b', TEST_BRANCH, '-o', self._output_dir)
Simon Glassdfb7e932014-09-05 19:00:20 -0600535 self.assertEqual(self._builder.count, self._total_builds)
536 self.assertEqual(self._builder.fail, 1)
537
538 # Remove the error. This should have no effect since the commit will
539 # not be rebuilt
540 del self._error['board2', 1]
541 self._make_calls = 0
Tom Riniaae62582019-10-07 17:17:36 -0400542 self._RunControl('-b', TEST_BRANCH, '-o', self._output_dir, clean_dir=False)
Simon Glassdfb7e932014-09-05 19:00:20 -0600543 self.assertEqual(self._builder.count, self._total_builds)
544 self.assertEqual(self._make_calls, 0)
545 self.assertEqual(self._builder.fail, 1)
546
547 # Now use the -F flag to force rebuild of the bad commit
Tom Riniaae62582019-10-07 17:17:36 -0400548 self._RunControl('-b', TEST_BRANCH, '-o', self._output_dir, '-F', clean_dir=False)
Simon Glassdfb7e932014-09-05 19:00:20 -0600549 self.assertEqual(self._builder.count, self._total_builds)
550 self.assertEqual(self._builder.fail, 0)
Simon Glasseb70a2c2020-04-09 15:08:51 -0600551 self.assertEqual(self._make_calls, 2)
Simon Glassf7582ce2014-09-05 19:00:22 -0600552
553 def testBranchWithSlash(self):
554 """Test building a branch with a '/' in the name"""
555 self._test_branch = '/__dev/__testbranch'
556 self._RunControl('-b', self._test_branch, clean_dir=False)
557 self.assertEqual(self._builder.count, self._total_builds)
558 self.assertEqual(self._builder.fail, 0)
Lothar Waßmann409fc022018-04-08 05:14:11 -0600559
Simon Glass166a98a2020-04-17 17:51:33 -0600560 def testEnvironment(self):
561 """Test that the done and environment files are written to out-env"""
562 self._RunControl('-o', self._output_dir)
563 board0_dir = os.path.join(self._output_dir, 'current', 'board0')
564 self.assertTrue(os.path.exists(os.path.join(board0_dir, 'done')))
565 self.assertTrue(os.path.exists(os.path.join(board0_dir, 'out-env')))
566
Simon Glassd829f122020-03-18 09:42:42 -0600567 def testWorkInOutput(self):
568 """Test the -w option which should write directly to the output dir"""
569 board_list = board.Boards()
570 board_list.AddBoard(board.Board(*boards[0]))
571 self._RunControl('-o', self._output_dir, '-w', clean_dir=False,
572 boards=board_list)
573 self.assertTrue(
574 os.path.exists(os.path.join(self._output_dir, 'u-boot')))
Simon Glass60b285f2020-04-17 17:51:34 -0600575 self.assertTrue(
576 os.path.exists(os.path.join(self._output_dir, 'done')))
577 self.assertTrue(
578 os.path.exists(os.path.join(self._output_dir, 'out-env')))
Simon Glassd829f122020-03-18 09:42:42 -0600579
580 def testWorkInOutputFail(self):
581 """Test the -w option failures"""
582 with self.assertRaises(SystemExit) as e:
583 self._RunControl('-o', self._output_dir, '-w', clean_dir=False)
584 self.assertIn("single board", str(e.exception))
585 self.assertFalse(
586 os.path.exists(os.path.join(self._output_dir, 'u-boot')))
587
588 board_list = board.Boards()
589 board_list.AddBoard(board.Board(*boards[0]))
590 with self.assertRaises(SystemExit) as e:
591 self._RunControl('-b', self._test_branch, '-o', self._output_dir,
592 '-w', clean_dir=False, boards=board_list)
593 self.assertIn("single commit", str(e.exception))
Simon Glass88daaef2020-04-17 17:51:32 -0600594
595 board_list = board.Boards()
596 board_list.AddBoard(board.Board(*boards[0]))
597 with self.assertRaises(SystemExit) as e:
598 self._RunControl('-w', clean_dir=False)
599 self.assertIn("specify -o", str(e.exception))