blob: 82daf05f376a12841fc49f83b67b020e149af442 [file] [log] [blame]
Mike Frysingere58c0e22017-10-04 15:43:30 -04001# -*- coding: utf-8 -*-
Don Garrettc4114cc2016-11-01 20:04:06 -07002# Copyright 2016 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.
5
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -07006"""Unit tests for chromite.scripts.cbuildbot_launch."""
Don Garrettc4114cc2016-11-01 20:04:06 -07007
8from __future__ import print_function
9
Don Garrett86881cb2017-02-15 15:41:55 -080010import mock
Don Garrett7ade05a2017-02-17 13:31:47 -080011import os
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -070012import time
Don Garrett86881cb2017-02-15 15:41:55 -080013
14from chromite.cbuildbot import repository
Benjamin Gordon90b2dd92018-04-12 14:04:21 -060015from chromite.lib import build_summary
Don Garrett861e9182017-05-15 15:30:23 -070016from chromite.lib import constants
Don Garrett597ddff2017-02-17 18:29:37 -080017from chromite.lib import cros_build_lib
Benjamin Gordon74645232018-05-04 17:40:42 -060018from chromite.lib import cros_sdk_lib
Don Garrett7ade05a2017-02-17 13:31:47 -080019from chromite.lib import cros_test_lib
Don Garrett86881cb2017-02-15 15:41:55 -080020from chromite.lib import osutils
Don Garrett0c54ed72017-03-03 11:18:57 -080021from chromite.scripts import cbuildbot_launch
Don Garrett86881cb2017-02-15 15:41:55 -080022
Don Garrett86881cb2017-02-15 15:41:55 -080023EXPECTED_MANIFEST_URL = 'https://chrome-internal-review.googlesource.com/chromeos/manifest-internal' # pylint: disable=line-too-long
Don Garrettc4114cc2016-11-01 20:04:06 -070024
25
Don Garrettacbb2392017-05-11 18:27:41 -070026# It's reasonable for unittests to look at internals.
27# pylint: disable=protected-access
28
29
Don Garrett8d314792017-05-18 13:11:42 -070030class FakeException(Exception):
31 """Test exception to raise during tests."""
32
33
Don Garrett0c54ed72017-03-03 11:18:57 -080034class CbuildbotLaunchTest(cros_test_lib.MockTestCase):
35 """Tests for cbuildbot_launch script."""
Don Garrettc4114cc2016-11-01 20:04:06 -070036
Don Garrett86881cb2017-02-15 15:41:55 -080037 def testPreParseArguments(self):
Don Garrettc4114cc2016-11-01 20:04:06 -070038 """Test that we can correctly extract branch values from cbuildbot args."""
Don Garrett597ddff2017-02-17 18:29:37 -080039 CASES = (
40 (['--buildroot', '/buildroot', 'daisy-incremental'],
41 (None, '/buildroot', None)),
42
43 (['--buildbot', '--buildroot', '/buildroot',
44 '--git-cache-dir', '/git-cache',
45 '-b', 'release-R57-9202.B',
46 'daisy-incremental'],
47 ('release-R57-9202.B', '/buildroot', '/git-cache')),
48
49 (['--debug', '--buildbot', '--notests',
50 '--buildroot', '/buildroot',
51 '--git-cache-dir', '/git-cache',
52 '--branch', 'release-R57-9202.B',
53 'daisy-incremental'],
54 ('release-R57-9202.B', '/buildroot', '/git-cache')),
Don Garrettc4114cc2016-11-01 20:04:06 -070055 )
56
Don Garrett597ddff2017-02-17 18:29:37 -080057 for cmd_args, expected in CASES:
58 expected_branch, expected_buildroot, expected_cache_dir = expected
59
Don Garrett0c54ed72017-03-03 11:18:57 -080060 options = cbuildbot_launch.PreParseArguments(cmd_args)
Don Garrett597ddff2017-02-17 18:29:37 -080061
62 self.assertEqual(options.branch, expected_branch)
63 self.assertEqual(options.buildroot, expected_buildroot)
64 self.assertEqual(options.git_cache_dir, expected_cache_dir)
Don Garrett86881cb2017-02-15 15:41:55 -080065
Don Garrettf324bc32017-05-23 14:00:53 -070066 def testInitialCheckout(self):
Don Garrett86881cb2017-02-15 15:41:55 -080067 """Test InitialCheckout with minimum settings."""
Don Garrettf324bc32017-05-23 14:00:53 -070068 mock_repo = mock.MagicMock()
69 mock_repo.branch = 'branch'
Don Garrett86881cb2017-02-15 15:41:55 -080070
Don Garrettf324bc32017-05-23 14:00:53 -070071 cbuildbot_launch.InitialCheckout(mock_repo)
Don Garrett86881cb2017-02-15 15:41:55 -080072
73 self.assertEqual(mock_repo.mock_calls, [
Don Garrettf324bc32017-05-23 14:00:53 -070074 mock.call.Sync(detach=True),
Don Garrett8d314792017-05-18 13:11:42 -070075 ])
76
Don Garrettf15d65b2017-04-12 12:39:55 -070077 def testConfigureGlobalEnvironment(self):
Don Garrett60967922017-04-12 18:51:44 -070078 """Ensure that we can setup our global runtime environment correctly."""
Don Garrett86fec482017-05-17 18:13:33 -070079
80 os.environ.pop('LANG', None)
81 os.environ['LC_MONETARY'] = 'bad'
82
Don Garrettf15d65b2017-04-12 12:39:55 -070083 cbuildbot_launch.ConfigureGlobalEnvironment()
84
Don Garrett86fec482017-05-17 18:13:33 -070085 # Verify umask is updated.
Don Garrettf15d65b2017-04-12 12:39:55 -070086 self.assertEqual(os.umask(0), 0o22)
87
Don Garrett86fec482017-05-17 18:13:33 -070088 # Verify ENVs are cleaned up.
89 self.assertEqual(os.environ['LANG'], 'en_US.UTF-8')
90 self.assertNotIn('LC_MONETARY', os.environ)
91
Don Garrettf15d65b2017-04-12 12:39:55 -070092
Benjamin Gordon121a2aa2018-05-04 16:24:45 -060093class RunTests(cros_test_lib.RunCommandTestCase):
Don Garrett0c54ed72017-03-03 11:18:57 -080094 """Tests for cbuildbot_launch script."""
Don Garrett597ddff2017-02-17 18:29:37 -080095
96 ARGS_BASE = ['--buildroot', '/buildroot']
Don Garrett5cd946b2017-07-20 13:42:20 -070097 EXPECTED_ARGS_BASE = ['--buildroot', '/cbuildbot_buildroot']
Don Garrett597ddff2017-02-17 18:29:37 -080098 ARGS_GIT_CACHE = ['--git-cache-dir', '/git-cache']
99 ARGS_CONFIG = ['config']
Don Garrettbf90cdf2017-05-19 15:54:02 -0700100 CMD = ['/cbuildbot_buildroot/chromite/bin/cbuildbot']
Don Garrett597ddff2017-02-17 18:29:37 -0800101
Don Garrett6e5c6b92018-04-06 17:58:49 -0700102 def verifyCbuildbot(self, args, expected_cmd, version):
Don Garrett86881cb2017-02-15 15:41:55 -0800103 """Ensure we invoke cbuildbot correctly."""
Don Garrett597ddff2017-02-17 18:29:37 -0800104 self.PatchObject(
105 cros_build_lib, 'GetTargetChromiteApiVersion', autospec=True,
106 return_value=version)
107
Don Garrett6e5c6b92018-04-06 17:58:49 -0700108 cbuildbot_launch.Cbuildbot('/cbuildbot_buildroot', '/depot_tools', args)
Don Garrett597ddff2017-02-17 18:29:37 -0800109
110 self.assertCommandCalled(
Don Garretta50bf492017-09-28 18:33:02 -0700111 expected_cmd, extra_env={'PATH': mock.ANY},
112 cwd='/cbuildbot_buildroot', error_code_ok=True)
Don Garrett597ddff2017-02-17 18:29:37 -0800113
Don Garrett6e5c6b92018-04-06 17:58:49 -0700114 def testCbuildbotSimple(self):
Don Garrett597ddff2017-02-17 18:29:37 -0800115 """Ensure we invoke cbuildbot correctly."""
Don Garrett6e5c6b92018-04-06 17:58:49 -0700116 self.verifyCbuildbot(
Don Garrett597ddff2017-02-17 18:29:37 -0800117 self.ARGS_BASE + self.ARGS_CONFIG,
Don Garrettbf90cdf2017-05-19 15:54:02 -0700118 self.CMD + self.ARGS_CONFIG + self.EXPECTED_ARGS_BASE,
Don Garrett597ddff2017-02-17 18:29:37 -0800119 (0, 4))
120
Don Garrett6e5c6b92018-04-06 17:58:49 -0700121 def testCbuildbotNotFiltered(self):
Don Garrett597ddff2017-02-17 18:29:37 -0800122 """Ensure we invoke cbuildbot correctly."""
Don Garrett6e5c6b92018-04-06 17:58:49 -0700123 self.verifyCbuildbot(
Don Garrett597ddff2017-02-17 18:29:37 -0800124 self.ARGS_BASE + self.ARGS_CONFIG + self.ARGS_GIT_CACHE,
Don Garrettbf90cdf2017-05-19 15:54:02 -0700125 (self.CMD + self.ARGS_CONFIG + self.EXPECTED_ARGS_BASE +
126 self.ARGS_GIT_CACHE),
Don Garrett597ddff2017-02-17 18:29:37 -0800127 (0, 4))
128
Don Garrett6e5c6b92018-04-06 17:58:49 -0700129 def testCbuildbotFiltered(self):
Don Garrett597ddff2017-02-17 18:29:37 -0800130 """Ensure we invoke cbuildbot correctly."""
Don Garrett6e5c6b92018-04-06 17:58:49 -0700131 self.verifyCbuildbot(
Don Garrett597ddff2017-02-17 18:29:37 -0800132 self.ARGS_BASE + self.ARGS_CONFIG + self.ARGS_GIT_CACHE,
Don Garrettbf90cdf2017-05-19 15:54:02 -0700133 self.CMD + self.ARGS_CONFIG + self.EXPECTED_ARGS_BASE,
Don Garrett597ddff2017-02-17 18:29:37 -0800134 (0, 2))
Don Garrettc4114cc2016-11-01 20:04:06 -0700135
Don Garrett86881cb2017-02-15 15:41:55 -0800136 def testMainMin(self):
137 """Test a minimal set of command line options."""
Don Garrett597ddff2017-02-17 18:29:37 -0800138 self.PatchObject(osutils, 'SafeMakedirs', autospec=True)
139 self.PatchObject(cros_build_lib, 'GetTargetChromiteApiVersion',
Don Garrett861e9182017-05-15 15:30:23 -0700140 autospec=True, return_value=(constants.REEXEC_API_MAJOR,
141 constants.REEXEC_API_MINOR))
Don Garrettf324bc32017-05-23 14:00:53 -0700142 mock_repo = mock.MagicMock()
143 mock_repo.branch = 'master'
Don Garrettbf90cdf2017-05-19 15:54:02 -0700144 mock_repo.directory = '/root/repository'
145
Don Garrettadf0f762018-07-27 11:36:53 -0700146 self.PatchObject(repository, 'IsARepoRoot', autospec=True,
147 return_value=True)
Don Garrettf324bc32017-05-23 14:00:53 -0700148 mock_repo_create = self.PatchObject(repository, 'RepoRepository',
149 autospec=True, return_value=mock_repo)
Don Garrettbf90cdf2017-05-19 15:54:02 -0700150 mock_clean = self.PatchObject(cbuildbot_launch, 'CleanBuildRoot',
Don Garrett0c54ed72017-03-03 11:18:57 -0800151 autospec=True)
152 mock_checkout = self.PatchObject(cbuildbot_launch, 'InitialCheckout',
Don Garrett86881cb2017-02-15 15:41:55 -0800153 autospec=True)
Benjamin Gordonaee36b82018-02-05 14:25:26 -0700154 mock_cleanup_chroot = self.PatchObject(cbuildbot_launch, 'CleanupChroot',
155 autospec=True)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600156 mock_set_last_build_state = self.PatchObject(
157 cbuildbot_launch, 'SetLastBuildState', autospec=True)
158
159 expected_build_state = build_summary.BuildSummary(
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600160 build_number=0, master_build_id=0, status=mock.ANY,
161 buildroot_layout=2, branch='master')
Don Garrett7ade05a2017-02-17 13:31:47 -0800162
Don Garrettbf90cdf2017-05-19 15:54:02 -0700163 cbuildbot_launch._main(['-r', '/root', 'config'])
Don Garrettc4114cc2016-11-01 20:04:06 -0700164
Don Garrettf324bc32017-05-23 14:00:53 -0700165 # Did we create the repo instance correctly?
166 self.assertEqual(mock_repo_create.mock_calls,
Don Garrettbf90cdf2017-05-19 15:54:02 -0700167 [mock.call(EXPECTED_MANIFEST_URL, '/root/repository',
Don Garrettadf0f762018-07-27 11:36:53 -0700168 git_cache_dir=None, branch='master',
169 referenced_repo=constants.SOURCE_ROOT)])
Don Garrettf324bc32017-05-23 14:00:53 -0700170
Don Garrett7ade05a2017-02-17 13:31:47 -0800171 # Ensure we clean, as expected.
Don Garrettbf90cdf2017-05-19 15:54:02 -0700172 self.assertEqual(mock_clean.mock_calls, [
Don Garrettd1d90dd2017-06-13 17:35:52 -0700173 mock.call('/root', mock_repo,
174 {
175 'branch_name': 'master',
176 'tryjob': False,
177 'build_config': 'config',
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600178 },
179 expected_build_state)])
Don Garrett7ade05a2017-02-17 13:31:47 -0800180
Don Garrett86881cb2017-02-15 15:41:55 -0800181 # Ensure we checkout, as expected.
182 self.assertEqual(mock_checkout.mock_calls,
Don Garrettf324bc32017-05-23 14:00:53 -0700183 [mock.call(mock_repo)])
Don Garrettc4114cc2016-11-01 20:04:06 -0700184
Don Garrett86881cb2017-02-15 15:41:55 -0800185 # Ensure we invoke cbuildbot, as expected.
186 self.assertCommandCalled(
Don Garrett5cd946b2017-07-20 13:42:20 -0700187 [
188 '/root/repository/chromite/bin/cbuildbot',
189 'config',
190 '-r', '/root/repository',
Don Garrettb497f552018-07-09 16:01:13 -0700191 '--workspace', '/root/workspace',
Don Garrett5cd946b2017-07-20 13:42:20 -0700192 '--ts-mon-task-num', '1',
193 ],
Don Garretta50bf492017-09-28 18:33:02 -0700194 extra_env={'PATH': mock.ANY},
Don Garrettbf90cdf2017-05-19 15:54:02 -0700195 cwd='/root/repository',
Don Garrettacbb2392017-05-11 18:27:41 -0700196 error_code_ok=True)
Don Garrettc4114cc2016-11-01 20:04:06 -0700197
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600198 # Ensure we saved the final state, as expected.
199 self.assertEqual(expected_build_state.status,
200 constants.BUILDER_STATUS_PASSED)
201 self.assertEqual(mock_set_last_build_state.mock_calls, [
202 mock.call('/root', expected_build_state)])
203
Benjamin Gordonaee36b82018-02-05 14:25:26 -0700204 # Ensure we clean the chroot, as expected.
205 self.assertEqual(mock_cleanup_chroot.mock_calls, [
206 mock.call('/root/repository')])
207
Don Garrettadf0f762018-07-27 11:36:53 -0700208 def testMainGitCacheValidRepo(self):
209 """Test having both git cache and a reference repo available."""
210 self.PatchObject(osutils, 'SafeMakedirs', autospec=True)
211 self.PatchObject(cros_build_lib, 'GetTargetChromiteApiVersion',
212 autospec=True, return_value=(constants.REEXEC_API_MAJOR,
213 constants.REEXEC_API_MINOR))
214 mock_repo = mock.MagicMock()
215 mock_repo.branch = 'master'
216 mock_repo.directory = '/root/repository'
217
218 self.PatchObject(
219 repository, 'IsARepoRoot', autospec=True, return_value=True)
220 mock_repo_create = self.PatchObject(
221 repository, 'RepoRepository', autospec=True, return_value=mock_repo)
222 self.PatchObject(cbuildbot_launch, 'CleanBuildRoot', autospec=True)
223 self.PatchObject(cbuildbot_launch, 'InitialCheckout', autospec=True)
224 self.PatchObject(cbuildbot_launch, 'CleanupChroot', autospec=True)
225 self.PatchObject(cbuildbot_launch, 'SetLastBuildState', autospec=True)
226
227 cbuildbot_launch._main(['-r', '/root', 'config',
228 '--git-cache', '/git-cache'])
229
230 # Ensure we prefer the referenced repo to the git-cache argument.
231 self.assertEqual(mock_repo_create.mock_calls,
232 [mock.call(EXPECTED_MANIFEST_URL, '/root/repository',
233 git_cache_dir=None, branch='master',
234 referenced_repo=constants.SOURCE_ROOT)])
235
236 # Ensure we still pass along git cache to cbuildbot.
237 self.assertCommandCalled(
238 [
239 '/root/repository/chromite/bin/cbuildbot',
240 'config',
241 '-r', '/root/repository',
242 '--git-cache-dir', '/git-cache',
243 '--workspace', '/root/workspace',
244 '--ts-mon-task-num', '1',
245 ],
246 extra_env={'PATH': mock.ANY},
247 cwd='/root/repository',
248 error_code_ok=True)
249
Don Garrett86881cb2017-02-15 15:41:55 -0800250 def testMainMax(self):
Don Garrett597ddff2017-02-17 18:29:37 -0800251 """Test a larger set of command line options."""
252 self.PatchObject(osutils, 'SafeMakedirs', autospec=True)
253 self.PatchObject(cros_build_lib, 'GetTargetChromiteApiVersion',
Don Garrett861e9182017-05-15 15:30:23 -0700254 autospec=True, return_value=(constants.REEXEC_API_MAJOR,
255 constants.REEXEC_API_MINOR))
Don Garrettf324bc32017-05-23 14:00:53 -0700256 mock_repo = mock.MagicMock()
257 mock_repo.branch = 'branch'
Don Garrettbf90cdf2017-05-19 15:54:02 -0700258 mock_repo.directory = '/root/repository'
259
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600260 mock_summary = build_summary.BuildSummary(
261 build_number=313,
262 master_build_id=123123123,
263 status=constants.BUILDER_STATUS_FAILED,
264 buildroot_layout=cbuildbot_launch.BUILDROOT_BUILDROOT_LAYOUT,
265 branch='branch')
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600266
267 mock_get_last_build_state = self.PatchObject(
268 cbuildbot_launch, 'GetLastBuildState', autospec=True,
269 return_value=mock_summary)
Don Garrettadf0f762018-07-27 11:36:53 -0700270 self.PatchObject(repository, 'IsARepoRoot', autospec=True,
271 return_value=False)
Don Garrettf324bc32017-05-23 14:00:53 -0700272 mock_repo_create = self.PatchObject(repository, 'RepoRepository',
273 autospec=True, return_value=mock_repo)
Don Garrettbf90cdf2017-05-19 15:54:02 -0700274 mock_clean = self.PatchObject(cbuildbot_launch, 'CleanBuildRoot',
Don Garrett0c54ed72017-03-03 11:18:57 -0800275 autospec=True)
276 mock_checkout = self.PatchObject(cbuildbot_launch, 'InitialCheckout',
Don Garrett86881cb2017-02-15 15:41:55 -0800277 autospec=True)
Benjamin Gordonaee36b82018-02-05 14:25:26 -0700278 mock_cleanup_chroot = self.PatchObject(cbuildbot_launch, 'CleanupChroot',
279 autospec=True)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600280 mock_set_last_build_state = self.PatchObject(
281 cbuildbot_launch, 'SetLastBuildState', autospec=True)
Don Garrettc4114cc2016-11-01 20:04:06 -0700282
Don Garrettbf90cdf2017-05-19 15:54:02 -0700283 cbuildbot_launch._main(['--buildroot', '/root',
Don Garrettacbb2392017-05-11 18:27:41 -0700284 '--branch', 'branch',
285 '--git-cache-dir', '/git-cache',
Don Garrettd1d90dd2017-06-13 17:35:52 -0700286 '--remote-trybot',
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600287 '--master-build-id', '123456789',
288 '--buildnumber', '314',
Don Garrettacbb2392017-05-11 18:27:41 -0700289 'config'])
Don Garrettc4114cc2016-11-01 20:04:06 -0700290
Don Garrettf324bc32017-05-23 14:00:53 -0700291 # Did we create the repo instance correctly?
292 self.assertEqual(mock_repo_create.mock_calls,
Don Garrettbf90cdf2017-05-19 15:54:02 -0700293 [mock.call(EXPECTED_MANIFEST_URL, '/root/repository',
Don Garrettadf0f762018-07-27 11:36:53 -0700294 git_cache_dir='/git-cache', branch='branch',
295 referenced_repo=None)])
Don Garrettf324bc32017-05-23 14:00:53 -0700296
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600297 # Ensure we look up the previous status.
298 self.assertEqual(mock_get_last_build_state.mock_calls, [
299 mock.call('/root')])
300
Don Garrett7ade05a2017-02-17 13:31:47 -0800301 # Ensure we clean, as expected.
Don Garrettbf90cdf2017-05-19 15:54:02 -0700302 self.assertEqual(mock_clean.mock_calls, [
Don Garrettd1d90dd2017-06-13 17:35:52 -0700303 mock.call('/root',
304 mock_repo,
305 {
306 'branch_name': 'branch',
307 'tryjob': True,
308 'build_config': 'config',
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600309 },
310 build_summary.BuildSummary(
311 build_number=314,
312 master_build_id=123456789,
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600313 status=mock.ANY,
314 branch='branch',
315 buildroot_layout=2
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600316 ))])
Don Garrett7ade05a2017-02-17 13:31:47 -0800317
Don Garrett86881cb2017-02-15 15:41:55 -0800318 # Ensure we checkout, as expected.
319 self.assertEqual(mock_checkout.mock_calls,
Don Garrettf324bc32017-05-23 14:00:53 -0700320 [mock.call(mock_repo)])
Don Garrett86881cb2017-02-15 15:41:55 -0800321
322 # Ensure we invoke cbuildbot, as expected.
323 self.assertCommandCalled(
Don Garrett5cd946b2017-07-20 13:42:20 -0700324 [
325 '/root/repository/chromite/bin/cbuildbot',
326 'config',
327 '--buildroot', '/root/repository',
328 '--branch', 'branch',
329 '--git-cache-dir', '/git-cache',
330 '--remote-trybot',
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600331 '--master-build-id', '123456789',
332 '--buildnumber', '314',
333 '--previous-build-state',
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600334 'eyJzdGF0dXMiOiAiZmFpbCIsICJtYXN0ZXJfYnVpbGRfaWQiOiAxMjMxMjMxMj'
335 'MsICJidWlsZF9udW1iZXIiOiAzMTMsICJidWlsZHJvb3RfbGF5b3V0IjogMiwg'
336 'ImJyYW5jaCI6ICJicmFuY2gifQ==',
Don Garrettb497f552018-07-09 16:01:13 -0700337 '--workspace', '/root/workspace',
Don Garrett5cd946b2017-07-20 13:42:20 -0700338 '--ts-mon-task-num', '1',
339 ],
Don Garretta50bf492017-09-28 18:33:02 -0700340 extra_env={'PATH': mock.ANY},
Don Garrettbf90cdf2017-05-19 15:54:02 -0700341 cwd='/root/repository',
Don Garrettacbb2392017-05-11 18:27:41 -0700342 error_code_ok=True)
Don Garrett7ade05a2017-02-17 13:31:47 -0800343
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600344 # Ensure we write the final build state, as expected.
345 final_state = build_summary.BuildSummary(
346 build_number=314,
347 master_build_id=123456789,
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600348 status=constants.BUILDER_STATUS_PASSED,
349 buildroot_layout=2,
350 branch='branch')
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600351 self.assertEqual(mock_set_last_build_state.mock_calls, [
352 mock.call('/root', final_state)])
353
Benjamin Gordonaee36b82018-02-05 14:25:26 -0700354 # Ensure we clean the chroot, as expected.
355 self.assertEqual(mock_cleanup_chroot.mock_calls, [
356 mock.call('/root/repository')])
357
Don Garrett7ade05a2017-02-17 13:31:47 -0800358
Don Garrettbf90cdf2017-05-19 15:54:02 -0700359class CleanBuildRootTest(cros_test_lib.MockTempDirTestCase):
360 """Tests for CleanBuildRoot method."""
Don Garrett7ade05a2017-02-17 13:31:47 -0800361
362 def setUp(self):
363 """Create standard buildroot contents for cleanup."""
Don Garrettbf90cdf2017-05-19 15:54:02 -0700364 self.root = os.path.join(self.tempdir)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600365 self.previous_build_state = os.path.join(
366 self.root, '.cbuildbot_build_state.json')
Don Garrettbf90cdf2017-05-19 15:54:02 -0700367 self.buildroot = os.path.join(self.root, 'buildroot')
368 self.repo = os.path.join(self.buildroot, '.repo/repo')
Don Garrett36650112018-06-28 15:54:34 -0700369 self.chroot = os.path.join(self.buildroot, 'chroot')
Don Garrettbf90cdf2017-05-19 15:54:02 -0700370 self.general = os.path.join(self.buildroot, 'general/general')
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700371 self.cache = os.path.join(self.buildroot, '.cache')
372 self.distfiles = os.path.join(self.cache, 'distfiles')
Don Garrett7ade05a2017-02-17 13:31:47 -0800373
Don Garrettf324bc32017-05-23 14:00:53 -0700374 self.mock_repo = mock.MagicMock()
Don Garrettbf90cdf2017-05-19 15:54:02 -0700375 self.mock_repo.directory = self.buildroot
Don Garrettf324bc32017-05-23 14:00:53 -0700376
Don Garrettacbb2392017-05-11 18:27:41 -0700377 self.metrics = {}
378
Benjamin Gordon8642bcc2018-05-01 13:49:56 -0600379 def populateBuildroot(self, previous_build_state=None):
Don Garrett7ade05a2017-02-17 13:31:47 -0800380 """Create standard buildroot contents for cleanup."""
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600381 if previous_build_state:
382 osutils.SafeMakedirs(self.root)
383 osutils.WriteFile(self.previous_build_state, previous_build_state)
384
Don Garrett7ade05a2017-02-17 13:31:47 -0800385 # Create files.
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700386 for f in (self.repo, self.chroot, self.general, self.distfiles):
Don Garrette17e1d92017-04-12 15:28:19 -0700387 osutils.Touch(f, makedirs=True)
Don Garrett7ade05a2017-02-17 13:31:47 -0800388
Don Garrette17e1d92017-04-12 15:28:19 -0700389 def testNoBuildroot(self):
Don Garrettbf90cdf2017-05-19 15:54:02 -0700390 """Test CleanBuildRoot with no history."""
Don Garrettf324bc32017-05-23 14:00:53 -0700391 self.mock_repo.branch = 'master'
392
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600393 build_state = build_summary.BuildSummary(
394 status=constants.BUILDER_STATUS_INFLIGHT,
395 buildroot_layout=cbuildbot_launch.BUILDROOT_BUILDROOT_LAYOUT,
396 branch='master')
Don Garrettbf90cdf2017-05-19 15:54:02 -0700397 cbuildbot_launch.CleanBuildRoot(
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600398 self.root, self.mock_repo, self.metrics, build_state)
Don Garrett7ade05a2017-02-17 13:31:47 -0800399
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600400 new_summary = cbuildbot_launch.GetLastBuildState(self.root)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600401 self.assertEqual(new_summary.buildroot_layout, 2)
402 self.assertEqual(new_summary.branch, 'master')
403 self.assertIsNotNone(new_summary.distfiles_ts)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600404 self.assertEqual(new_summary, build_state)
Don Garrett7ade05a2017-02-17 13:31:47 -0800405
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600406 self.assertExists(self.previous_build_state)
407
Don Garrett7ade05a2017-02-17 13:31:47 -0800408 def testBuildrootNoState(self):
Don Garrettbf90cdf2017-05-19 15:54:02 -0700409 """Test CleanBuildRoot with no state information."""
Don Garrett7ade05a2017-02-17 13:31:47 -0800410 self.populateBuildroot()
Don Garrettf324bc32017-05-23 14:00:53 -0700411 self.mock_repo.branch = 'master'
Don Garrett7ade05a2017-02-17 13:31:47 -0800412
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600413 build_state = build_summary.BuildSummary(
414 status=constants.BUILDER_STATUS_INFLIGHT,
415 buildroot_layout=cbuildbot_launch.BUILDROOT_BUILDROOT_LAYOUT,
416 branch='master')
Don Garrettbf90cdf2017-05-19 15:54:02 -0700417 cbuildbot_launch.CleanBuildRoot(
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600418 self.root, self.mock_repo, self.metrics, build_state)
Don Garrett7ade05a2017-02-17 13:31:47 -0800419
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600420 new_summary = cbuildbot_launch.GetLastBuildState(self.root)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600421 self.assertEqual(new_summary.buildroot_layout, 2)
422 self.assertEqual(new_summary.branch, 'master')
423 self.assertIsNotNone(new_summary.distfiles_ts)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600424 self.assertEqual(new_summary, build_state)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700425
Don Garrett60967922017-04-12 18:51:44 -0700426 self.assertNotExists(self.repo)
Don Garrett7ade05a2017-02-17 13:31:47 -0800427 self.assertNotExists(self.chroot)
Don Garrett60967922017-04-12 18:51:44 -0700428 self.assertNotExists(self.general)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700429 self.assertNotExists(self.distfiles)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600430 self.assertExists(self.previous_build_state)
Don Garrett7ade05a2017-02-17 13:31:47 -0800431
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600432 def testBuildrootFormatMismatch(self):
433 """Test CleanBuildRoot with buildroot layout mismatch."""
434 old_build_state = build_summary.BuildSummary(
435 status=constants.BUILDER_STATUS_PASSED,
436 buildroot_layout=1,
437 branch='master')
438 self.populateBuildroot(previous_build_state=old_build_state.to_json())
439 self.mock_repo.branch = 'master'
440
441 build_state = build_summary.BuildSummary(
442 status=constants.BUILDER_STATUS_INFLIGHT,
443 buildroot_layout=cbuildbot_launch.BUILDROOT_BUILDROOT_LAYOUT,
444 branch='master')
445 cbuildbot_launch.CleanBuildRoot(
446 self.root, self.mock_repo, self.metrics, build_state)
447
448 new_summary = cbuildbot_launch.GetLastBuildState(self.root)
449 self.assertEqual(new_summary.buildroot_layout, 2)
450 self.assertEqual(new_summary.branch, 'master')
451 self.assertIsNotNone(new_summary.distfiles_ts)
452 self.assertEqual(new_summary, build_state)
453
454 self.assertNotExists(self.repo)
455 self.assertNotExists(self.chroot)
456 self.assertNotExists(self.general)
457 self.assertNotExists(self.distfiles)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600458 self.assertExists(self.previous_build_state)
459
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600460 def testBuildrootBranchChange(self):
461 """Test CleanBuildRoot with a change in branches."""
462 old_build_state = build_summary.BuildSummary(
463 status=constants.BUILDER_STATUS_PASSED,
464 buildroot_layout=2,
465 branch='branchA')
466 self.populateBuildroot(previous_build_state=old_build_state.to_json())
467 self.mock_repo.branch = 'branchB'
Benjamin Gordon74645232018-05-04 17:40:42 -0600468 m = self.PatchObject(cros_sdk_lib, 'CleanupChrootMount')
Don Garrett7ade05a2017-02-17 13:31:47 -0800469
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600470 build_state = build_summary.BuildSummary(
471 status=constants.BUILDER_STATUS_INFLIGHT,
472 buildroot_layout=cbuildbot_launch.BUILDROOT_BUILDROOT_LAYOUT,
473 branch='branchB')
Don Garrettbf90cdf2017-05-19 15:54:02 -0700474 cbuildbot_launch.CleanBuildRoot(
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600475 self.root, self.mock_repo, self.metrics, build_state)
Don Garrett7ade05a2017-02-17 13:31:47 -0800476
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600477 new_summary = cbuildbot_launch.GetLastBuildState(self.root)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600478 self.assertEqual(new_summary.buildroot_layout, 2)
479 self.assertEqual(new_summary.branch, 'branchB')
480 self.assertIsNotNone(new_summary.distfiles_ts)
481 self.assertEqual(new_summary, build_state)
482
483 self.assertExists(self.repo)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600484 self.assertExists(self.general)
485 self.assertNotExists(self.distfiles)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600486 self.assertExists(self.previous_build_state)
Don Garrett36650112018-06-28 15:54:34 -0700487 m.assert_called_with(self.chroot, delete=True)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600488
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600489 def testBuildrootBranchMatch(self):
490 """Test CleanBuildRoot with no change in branch."""
491 old_build_state = build_summary.BuildSummary(
492 status=constants.BUILDER_STATUS_PASSED,
493 buildroot_layout=2,
494 branch='branchA')
495 self.populateBuildroot(previous_build_state=old_build_state.to_json())
496 self.mock_repo.branch = 'branchA'
497
498 build_state = build_summary.BuildSummary(
499 status=constants.BUILDER_STATUS_INFLIGHT,
500 buildroot_layout=cbuildbot_launch.BUILDROOT_BUILDROOT_LAYOUT,
501 branch='branchA')
502 cbuildbot_launch.CleanBuildRoot(
503 self.root, self.mock_repo, self.metrics, build_state)
504
505 new_summary = cbuildbot_launch.GetLastBuildState(self.root)
506 self.assertEqual(new_summary.buildroot_layout, 2)
507 self.assertEqual(new_summary.branch, 'branchA')
508 self.assertIsNotNone(new_summary.distfiles_ts)
509 self.assertEqual(new_summary, build_state)
510
511 self.assertExists(self.repo)
512 self.assertExists(self.chroot)
513 self.assertExists(self.general)
514 self.assertExists(self.distfiles)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600515 self.assertExists(self.previous_build_state)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700516
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600517 def testBuildrootDistfilesRecentCache(self):
518 """Test CleanBuildRoot does not delete distfiles when cache is recent."""
519 seed_distfiles_ts = time.time() - 60
520 old_build_state = build_summary.BuildSummary(
521 status=constants.BUILDER_STATUS_PASSED,
522 buildroot_layout=2,
523 branch='branchA',
524 distfiles_ts=seed_distfiles_ts)
525 self.populateBuildroot(previous_build_state=old_build_state.to_json())
526 self.mock_repo.branch = 'branchA'
527
528 build_state = build_summary.BuildSummary(
529 status=constants.BUILDER_STATUS_INFLIGHT,
530 buildroot_layout=cbuildbot_launch.BUILDROOT_BUILDROOT_LAYOUT,
531 branch='branchA')
532 cbuildbot_launch.CleanBuildRoot(
533 self.root, self.mock_repo, self.metrics, build_state)
534
535 new_summary = cbuildbot_launch.GetLastBuildState(self.root)
536 self.assertEqual(new_summary.buildroot_layout, 2)
537 self.assertEqual(new_summary.branch, 'branchA')
538 # Same cache creation timestamp is rewritten to state.
539 self.assertEqual(new_summary.distfiles_ts, seed_distfiles_ts)
540 self.assertEqual(new_summary, build_state)
541
542 self.assertExists(self.repo)
543 self.assertExists(self.chroot)
544 self.assertExists(self.general)
545 self.assertExists(self.distfiles)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600546 self.assertExists(self.previous_build_state)
Don Garrette17e1d92017-04-12 15:28:19 -0700547
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600548 def testBuildrootDistfilesCacheExpired(self):
549 """Test CleanBuildRoot when the distfiles cache is too old."""
550 old_build_state = build_summary.BuildSummary(
551 status=constants.BUILDER_STATUS_PASSED,
552 buildroot_layout=2,
553 branch='branchA',
554 distfiles_ts=100.0)
555 self.populateBuildroot(previous_build_state=old_build_state.to_json())
556 self.mock_repo.branch = 'branchA'
557
558 build_state = build_summary.BuildSummary(
559 status=constants.BUILDER_STATUS_INFLIGHT,
560 buildroot_layout=cbuildbot_launch.BUILDROOT_BUILDROOT_LAYOUT,
561 branch='branchA')
562 cbuildbot_launch.CleanBuildRoot(
563 self.root, self.mock_repo, self.metrics, build_state)
564
565 new_summary = cbuildbot_launch.GetLastBuildState(self.root)
566 self.assertEqual(new_summary.buildroot_layout, 2)
567 self.assertEqual(new_summary.branch, 'branchA')
568 self.assertIsNotNone(new_summary.distfiles_ts)
569 self.assertEqual(new_summary, build_state)
570
571 self.assertExists(self.repo)
572 self.assertExists(self.chroot)
573 self.assertExists(self.general)
574 self.assertNotExists(self.distfiles)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600575 self.assertExists(self.previous_build_state)
576
577 def testBuildrootRepoCleanFailure(self):
578 """Test CleanBuildRoot with repo checkout failure."""
579 old_build_state = build_summary.BuildSummary(
580 status=constants.BUILDER_STATUS_PASSED,
581 buildroot_layout=1,
582 branch='branchA')
583 self.populateBuildroot(previous_build_state=old_build_state.to_json())
584 self.mock_repo.branch = 'branchA'
585 self.mock_repo.BuildRootGitCleanup.side_effect = Exception
586
587 build_state = build_summary.BuildSummary(
588 status=constants.BUILDER_STATUS_INFLIGHT,
589 buildroot_layout=cbuildbot_launch.BUILDROOT_BUILDROOT_LAYOUT,
590 branch='branchA')
591 cbuildbot_launch.CleanBuildRoot(
592 self.root, self.mock_repo, self.metrics, build_state)
593
594 new_summary = cbuildbot_launch.GetLastBuildState(self.root)
595 self.assertEqual(new_summary.buildroot_layout, 2)
596 self.assertEqual(new_summary.branch, 'branchA')
597 self.assertIsNotNone(new_summary.distfiles_ts)
598 self.assertEqual(new_summary, build_state)
599
600 self.assertNotExists(self.repo)
601 self.assertNotExists(self.chroot)
602 self.assertNotExists(self.general)
603 self.assertNotExists(self.distfiles)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600604 self.assertExists(self.previous_build_state)
Don Garrettf324bc32017-05-23 14:00:53 -0700605
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600606 def testGetCurrentBuildStateNoArgs(self):
607 """Tests GetCurrentBuildState without arguments."""
608 options = cbuildbot_launch.PreParseArguments([
609 '--buildroot', self.root, 'config'
610 ])
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600611 state = cbuildbot_launch.GetCurrentBuildState(options, 'master')
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600612
613 expected_state = build_summary.BuildSummary(
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600614 status=constants.BUILDER_STATUS_INFLIGHT,
615 buildroot_layout=2,
616 branch='master')
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600617 self.assertEqual(state, expected_state)
618
619 def testGetCurrentBuildStateHasArgs(self):
620 """Tests GetCurrentBuildState with arguments."""
621 options = cbuildbot_launch.PreParseArguments([
622 '--buildroot', self.root,
623 '--buildnumber', '20',
624 '--master-build-id', '50',
625 'config'
626 ])
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600627 state = cbuildbot_launch.GetCurrentBuildState(options, 'branchA')
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600628
629 expected_state = build_summary.BuildSummary(
630 build_number=20,
631 master_build_id=50,
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600632 status=constants.BUILDER_STATUS_INFLIGHT,
633 buildroot_layout=2,
634 branch='branchA')
635 self.assertEqual(state, expected_state)
636
637 def testGetCurrentBuildStateLayout(self):
638 """Test that GetCurrentBuildState uses the current buildroot layout."""
639 # Change to a future version.
640 self.PatchObject(cbuildbot_launch, 'BUILDROOT_BUILDROOT_LAYOUT', 22)
641
642 options = cbuildbot_launch.PreParseArguments([
643 '--buildroot', self.root, 'config'
644 ])
645 state = cbuildbot_launch.GetCurrentBuildState(options, 'branchA')
646
647 expected_state = build_summary.BuildSummary(
648 status=constants.BUILDER_STATUS_INFLIGHT,
649 buildroot_layout=22,
650 branch='branchA')
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600651 self.assertEqual(state, expected_state)
652
653 def testGetLastBuildStateNoFile(self):
654 """Tests GetLastBuildState if the file is missing."""
655 osutils.SafeMakedirs(self.root)
656 state = cbuildbot_launch.GetLastBuildState(self.root)
657 self.assertEqual(state, build_summary.BuildSummary())
658
659 def testGetLastBuildStateBadFile(self):
660 """Tests GetLastBuildState if the file contains invalid JSON."""
661 osutils.SafeMakedirs(self.root)
662 osutils.WriteFile(self.previous_build_state, '}}')
663 state = cbuildbot_launch.GetLastBuildState(self.root)
664 self.assertEqual(state, build_summary.BuildSummary())
665
666 def testGetLastBuildStateMissingBuildStatus(self):
667 """Tests GetLastBuildState if the file doesn't have a valid status."""
668 osutils.SafeMakedirs(self.root)
669 osutils.WriteFile(self.previous_build_state, '{"build_number": "3"}')
670 state = cbuildbot_launch.GetLastBuildState(self.root)
671 self.assertEqual(state, build_summary.BuildSummary())
672
673 def testGetLastBuildStateGoodFile(self):
674 """Tests GetLastBuildState on a good file."""
675 osutils.SafeMakedirs(self.root)
676 osutils.WriteFile(
677 self.previous_build_state,
678 '{"build_number": 1, "master_build_id": 3, "status": "pass"}')
679 state = cbuildbot_launch.GetLastBuildState(self.root)
680 self.assertEqual(
681 state,
682 build_summary.BuildSummary(
683 build_number=1, master_build_id=3, status='pass'))
684
685 def testSetLastBuildState(self):
686 """Verifies that SetLastBuildState writes to the expected file."""
687 osutils.SafeMakedirs(self.root)
688 old_state = build_summary.BuildSummary(
689 build_number=314,
690 master_build_id=2178,
691 status=constants.BUILDER_STATUS_PASSED)
692 cbuildbot_launch.SetLastBuildState(self.root, old_state)
693
694 saved_state = osutils.ReadFile(self.previous_build_state)
695 new_state = build_summary.BuildSummary()
696 new_state.from_json(saved_state)
697
698 self.assertEqual(old_state, new_state)