2 # Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
6 """Unittests for build stages."""
8 from __future__ import print_function
14 sys.path.insert(0, os.path.abspath('%s/../../..' % os.path.dirname(__file__)))
15 from chromite.cbuildbot import cbuildbot_config as config
16 from chromite.cbuildbot import commands
17 from chromite.cbuildbot import constants
18 from chromite.cbuildbot.cbuildbot_unittest import BuilderRunMock
19 from chromite.cbuildbot.stages import build_stages
20 from chromite.cbuildbot.stages import generic_stages_unittest
21 from chromite.lib import cros_build_lib
22 from chromite.lib import cros_build_lib_unittest
23 from chromite.lib import cros_test_lib
24 from chromite.lib import git
25 from chromite.lib import parallel
26 from chromite.lib import parallel_unittest
27 from chromite.lib import partial_mock
29 from chromite.cbuildbot.stages.generic_stages_unittest import patch
30 from chromite.cbuildbot.stages.generic_stages_unittest import patches
33 # pylint: disable=W0212,R0901
34 class InitSDKTest(generic_stages_unittest.RunCommandAbstractStageTest):
35 """Test building the SDK"""
38 self.PatchObject(cros_build_lib, 'GetChrootVersion', return_value='12')
40 def ConstructStage(self):
41 return build_stages.InitSDKStage(self._run)
43 def testFullBuildWithExistingChroot(self):
44 """Tests whether we create chroots for full builds."""
46 self._Run(dir_exists=True)
47 self.assertCommandContains(['cros_sdk'])
49 def testBinBuildWithMissingChroot(self):
50 """Tests whether we create chroots when needed."""
52 # Do not force chroot replacement in build config.
53 self._run._config.chroot_replace = False
54 self._Run(dir_exists=False)
55 self.assertCommandContains(['cros_sdk'])
57 def testFullBuildWithMissingChroot(self):
58 """Tests whether we create chroots when needed."""
60 self._Run(dir_exists=True)
61 self.assertCommandContains(['cros_sdk'])
63 def testFullBuildWithNoSDK(self):
64 """Tests whether the --nosdk option works."""
65 self._PrepareFull(extra_cmd_args=['--nosdk'])
66 self._Run(dir_exists=False)
67 self.assertCommandContains(['cros_sdk', '--bootstrap'])
69 def testBinBuildWithExistingChroot(self):
70 """Tests whether the --nosdk option works."""
71 self._PrepareFull(extra_cmd_args=['--nosdk'])
72 # Do not force chroot replacement in build config.
73 self._run._config.chroot_replace = False
74 self._Run(dir_exists=True)
75 self.assertCommandContains(['cros_sdk'], expected=False)
78 class SetupBoardTest(generic_stages_unittest.RunCommandAbstractStageTest):
79 """Test building the board"""
81 def ConstructStage(self):
82 return build_stages.SetupBoardStage(self._run, self._current_board)
84 def _RunFull(self, dir_exists=False):
85 """Helper for testing a full builder."""
87 self.assertCommandContains(['./update_chroot', '--nousepkg'])
88 cmd = ['./setup_board', '--board=%s' % self._current_board, '--nousepkg']
89 self.assertCommandContains(cmd, expected=not dir_exists)
90 cmd = ['./setup_board', '--skip_chroot_upgrade']
91 self.assertCommandContains(cmd)
93 def testFullBuildWithProfile(self):
94 """Tests whether full builds add profile flag when requested."""
95 self._PrepareFull(extra_config={'profile': 'foo'})
96 self._RunFull(dir_exists=False)
97 self.assertCommandContains(['./setup_board', '--profile=foo'])
99 def testFullBuildWithOverriddenProfile(self):
100 """Tests whether full builds add overridden profile flag when requested."""
101 self._PrepareFull(extra_cmd_args=['--profile', 'smock'])
102 self._RunFull(dir_exists=False)
103 self.assertCommandContains(['./setup_board', '--profile=smock'])
105 def testFullBuildWithLatestToolchain(self):
106 """Tests whether we use --nousepkg for creating the board"""
108 self._RunFull(dir_exists=False)
110 def _RunBin(self, dir_exists):
111 """Helper for testing a binary builder."""
112 self._Run(dir_exists)
113 usepkg_toolchain = (self._run.config.usepkg_toolchain and not
114 self._run.options.latest_toolchain)
115 self.assertCommandContains(['./update_chroot', '--nousepkg'],
116 expected=not usepkg_toolchain)
117 run_setup_board = not dir_exists or self._run.options.latest_toolchain
118 self.assertCommandContains(['./setup_board'], expected=run_setup_board)
119 cmd = ['./setup_board', '--skip_chroot_upgrade']
120 self.assertCommandContains(cmd, expected=run_setup_board)
121 cmd = ['./setup_board', '--nousepkg'],
122 self.assertCommandContains(cmd,
123 expected=run_setup_board and not self._run.config.usepkg_build_packages)
125 def testBinBuildWithBoard(self):
126 """Tests whether we don't create the board when it's there."""
128 self._RunBin(dir_exists=True)
130 def testBinBuildWithMissingBoard(self):
131 """Tests whether we create the board when it's missing."""
133 self._RunBin(dir_exists=False)
135 def testBinBuildWithLatestToolchain(self):
136 """Tests whether we use --nousepkg for creating the board."""
138 self._run.options.latest_toolchain = True
139 self._RunBin(dir_exists=False)
141 def testBinBuildWithNoToolchainPackages(self):
142 """Tests whether we use --nousepkg for creating the board."""
144 self._run.config.usepkg_toolchain = False
145 self._RunBin(dir_exists=False)
147 def testSDKBuild(self):
148 """Tests whether we use --skip_chroot_upgrade for SDK builds."""
149 extra_config = {'build_type': constants.CHROOT_BUILDER_TYPE}
150 self._PrepareFull(extra_config=extra_config)
151 self._Run(dir_exists=False)
152 self.assertCommandContains(['./update_chroot'], expected=False)
153 self.assertCommandContains(['./setup_board', '--skip_chroot_upgrade'])
156 class UprevStageTest(generic_stages_unittest.AbstractStageTest):
157 """Tests for the UprevStage class."""
160 self.mox.StubOutWithMock(commands, 'UprevPackages')
164 def ConstructStage(self):
165 return build_stages.UprevStage(self._run)
167 def testBuildRev(self):
168 """Uprevving the build without uprevving chrome."""
169 self._run.config['uprev'] = True
170 commands.UprevPackages(self.build_root, self._boards, [], enter_chroot=True)
176 """No paths are enabled."""
177 self._run.config['uprev'] = False
183 class BuildPackagesStageTest(generic_stages_unittest.AbstractStageTest):
184 """Tests BuildPackagesStage."""
187 self._release_tag = None
189 self.StartPatcher(BuilderRunMock())
191 def ConstructStage(self):
192 self._run.attrs.release_tag = self._release_tag
193 return build_stages.BuildPackagesStage(self._run, self._current_board)
195 @contextlib.contextmanager
196 def RunStageWithConfig(self, mock_configurator=None):
197 """Run the given config"""
199 with cros_build_lib_unittest.RunCommandMock() as rc:
200 rc.SetDefaultCmdResult()
201 if mock_configurator:
202 mock_configurator(rc)
203 with cros_test_lib.OutputCapturer():
204 with cros_test_lib.LoggingCapturer():
209 except AssertionError as ex:
210 msg = '%s failed the following test:\n%s' % (self._bot_id, ex)
211 raise AssertionError(msg)
213 def RunTestsWithBotId(self, bot_id, options_tests=True):
214 """Test with the config for the specified bot_id."""
215 self._Prepare(bot_id)
216 self._run.options.tests = options_tests
218 with self.RunStageWithConfig() as rc:
219 cfg = self._run.config
220 rc.assertCommandContains(['./build_packages'])
221 rc.assertCommandContains(['./build_packages', '--skip_chroot_upgrade'])
222 rc.assertCommandContains(['./build_packages', '--nousepkg'],
223 expected=not cfg['usepkg_build_packages'])
224 build_tests = cfg['build_tests'] and self._run.options.tests
225 rc.assertCommandContains(['./build_packages', '--nowithautotest'],
226 expected=not build_tests)
228 def testAllConfigs(self):
229 """Test all major configurations"""
230 task = self.RunTestsWithBotId
231 with parallel.BackgroundTaskRunner(task) as queue:
232 # Loop through all major configuration types and pick one from each.
233 for bot_type in config.CONFIG_TYPE_DUMP_ORDER:
234 for bot_id in config.config:
235 if bot_id.endswith(bot_type):
236 # Skip any config without a board, since those configs do not
238 cfg = config.config[bot_id]
243 def testNoTests(self):
244 """Test that self.options.tests = False works."""
245 self.RunTestsWithBotId('x86-generic-paladin', options_tests=False)
248 class BuildImageStageMock(partial_mock.PartialMock):
249 """Partial mock for BuildImageStage."""
251 TARGET = 'chromite.cbuildbot.stages.build_stages.BuildImageStage'
252 ATTRS = ('_BuildImages', '_GenerateAuZip')
254 def _BuildImages(self, *args, **kwargs):
256 patch(os, 'symlink'),
257 patch(os, 'readlink', return_value='foo.txt')):
258 self.backup['_BuildImages'](*args, **kwargs)
260 def _GenerateAuZip(self, *args, **kwargs):
261 with patch(git, 'ReinterpretPathForChroot', return_value='/chroot/path'):
262 self.backup['_GenerateAuZip'](*args, **kwargs)
265 class BuildImageStageTest(BuildPackagesStageTest):
266 """Tests BuildImageStage."""
269 self.StartPatcher(BuildImageStageMock())
271 def ConstructStage(self):
272 return build_stages.BuildImageStage(self._run, self._current_board)
274 def RunTestsWithReleaseConfig(self, release_tag):
275 self._release_tag = release_tag
277 with parallel_unittest.ParallelMock():
278 with self.RunStageWithConfig() as rc:
279 cfg = self._run.config
280 cmd = ['./build_image', '--version=%s' % (self._release_tag or '')]
281 rc.assertCommandContains(cmd, expected=cfg['images'])
282 rc.assertCommandContains(['./image_to_vm.sh'],
283 expected=cfg['vm_tests'])
284 cmd = ['./build_library/generate_au_zip.py', '-o', '/chroot/path']
285 rc.assertCommandContains(cmd, expected=cfg['images'])
287 def RunTestsWithBotId(self, bot_id, options_tests=True):
288 """Test with the config for the specified bot_id."""
289 release_tag = '0.0.1'
290 self._Prepare(bot_id)
291 self._run.options.tests = options_tests
292 self._run.attrs.release_tag = release_tag
294 task = self.RunTestsWithReleaseConfig
295 steps = [lambda: task(tag) for tag in (None, release_tag)]
296 parallel.RunParallelSteps(steps)
299 if __name__ == '__main__':