blob: 8711f9c1312728f751635853bee3fbc3bad33ba3 [file] [log] [blame]
Simon Glassd4144e42014-09-05 19:00:13 -06001#
2# Copyright (c) 2014 Google, Inc
3#
4# SPDX-License-Identifier: GPL-2.0+
5#
6
7import os
8import shutil
9import sys
10import tempfile
11import unittest
12
13import cmdline
14import command
15import control
16import gitutil
17import terminal
18import toolchain
19
20class TestFunctional(unittest.TestCase):
21 """Functional test for buildman.
22
23 This aims to test from just below the invocation of buildman (parsing
24 of arguments) to 'make' and 'git' invocation. It is not a true
25 emd-to-end test, as it mocks git, make and the tool chain. But this
26 makes it easier to detect when the builder is doing the wrong thing,
27 since in many cases this test code will fail. For example, only a
28 very limited subset of 'git' arguments is supported - anything
29 unexpected will fail.
30 """
31 def setUp(self):
32 self._base_dir = tempfile.mkdtemp()
33 self._git_dir = os.path.join(self._base_dir, 'src')
34 self._buildman_pathname = sys.argv[0]
35 self._buildman_dir = os.path.dirname(sys.argv[0])
36 command.test_result = self._HandleCommand
37 self._toolchains = toolchain.Toolchains()
38 self._toolchains.Add('gcc', test=False)
39
40 def tearDown(self):
41 shutil.rmtree(self._base_dir)
42
43 def _RunBuildman(self, *args):
44 return command.RunPipe([[self._buildman_pathname] + list(args)],
45 capture=True, capture_stderr=True)
46
47 def _RunControl(self, *args):
48 sys.argv = [sys.argv[0]] + list(args)
49 options, args = cmdline.ParseArgs()
50 return control.DoBuildman(options, args, toolchains=self._toolchains,
51 make_func=self._HandleMake)
52
53 def testFullHelp(self):
54 command.test_result = None
55 result = self._RunBuildman('-H')
56 help_file = os.path.join(self._buildman_dir, 'README')
57 self.assertEqual(len(result.stdout), os.path.getsize(help_file))
58 self.assertEqual(0, len(result.stderr))
59 self.assertEqual(0, result.return_code)
60
61 def testHelp(self):
62 command.test_result = None
63 result = self._RunBuildman('-h')
64 help_file = os.path.join(self._buildman_dir, 'README')
65 self.assertTrue(len(result.stdout) > 1000)
66 self.assertEqual(0, len(result.stderr))
67 self.assertEqual(0, result.return_code)
68
69 def testGitSetup(self):
70 """Test gitutils.Setup(), from outside the module itself"""
71 command.test_result = command.CommandResult(return_code=1)
72 gitutil.Setup()
73 self.assertEqual(gitutil.use_no_decorate, False)
74
75 command.test_result = command.CommandResult(return_code=0)
76 gitutil.Setup()
77 self.assertEqual(gitutil.use_no_decorate, True)
78
79 def _HandleCommandGitLog(self, args):
80 if '-n0' in args:
81 return command.CommandResult(return_code=0)
82
83 # Not handled, so abort
84 print 'git log', args
85 sys.exit(1)
86
87 def _HandleCommandGit(self, in_args):
88 """Handle execution of a git command
89
90 This uses a hacked-up parser.
91
92 Args:
93 in_args: Arguments after 'git' from the command line
94 """
95 git_args = [] # Top-level arguments to git itself
96 sub_cmd = None # Git sub-command selected
97 args = [] # Arguments to the git sub-command
98 for arg in in_args:
99 if sub_cmd:
100 args.append(arg)
101 elif arg[0] == '-':
102 git_args.append(arg)
103 else:
104 sub_cmd = arg
105 if sub_cmd == 'config':
106 return command.CommandResult(return_code=0)
107 elif sub_cmd == 'log':
108 return self._HandleCommandGitLog(args)
109
110 # Not handled, so abort
111 print 'git', git_args, sub_cmd, args
112 sys.exit(1)
113
114 def _HandleCommandNm(self, args):
115 return command.CommandResult(return_code=0)
116
117 def _HandleCommandObjdump(self, args):
118 return command.CommandResult(return_code=0)
119
120 def _HandleCommandSize(self, args):
121 return command.CommandResult(return_code=0)
122
123 def _HandleCommand(self, **kwargs):
124 """Handle a command execution.
125
126 The command is in kwargs['pipe-list'], as a list of pipes, each a
127 list of commands. The command should be emulated as required for
128 testing purposes.
129
130 Returns:
131 A CommandResult object
132 """
133 pipe_list = kwargs['pipe_list']
134 if len(pipe_list) != 1:
135 print 'invalid pipe', kwargs
136 sys.exit(1)
137 cmd = pipe_list[0][0]
138 args = pipe_list[0][1:]
139 if cmd == 'git':
140 return self._HandleCommandGit(args)
141 elif cmd == './scripts/show-gnu-make':
142 return command.CommandResult(return_code=0, stdout='make')
143 elif cmd == 'nm':
144 return self._HandleCommandNm(args)
145 elif cmd == 'objdump':
146 return self._HandleCommandObjdump(args)
147 elif cmd == 'size':
148 return self._HandleCommandSize(args)
149
150 # Not handled, so abort
151 print 'unknown command', kwargs
152 sys.exit(1)
153 return command.CommandResult(return_code=0)
154
155 def _HandleMake(self, commit, brd, stage, cwd, *args, **kwargs):
156 """Handle execution of 'make'
157
158 Args:
159 commit: Commit object that is being built
160 brd: Board object that is being built
161 stage: Stage that we are at (mrproper, config, build)
162 cwd: Directory where make should be run
163 args: Arguments to pass to make
164 kwargs: Arguments to pass to command.RunPipe()
165 """
166 if stage == 'mrproper':
167 return command.CommandResult(return_code=0)
168 elif stage == 'config':
169 return command.CommandResult(return_code=0,
170 combined='Test configuration complete')
171 elif stage == 'build':
172 return command.CommandResult(return_code=0)
173
174 # Not handled, so abort
175 print 'make', stage
176 sys.exit(1)
177
178 def testCurrentSource(self):
179 """Very simple test to invoke buildman on the current source"""
180 self._RunControl()
181 lines = terminal.GetPrintTestLines()
182 self.assertTrue(lines[0].text.startswith('Building current source'))