blob: bef962670a2e34516cd1fc15ea04232a2d2cb53a [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
Don Garrett7ade05a2017-02-17 13:31:47 -080018from chromite.lib import cros_test_lib
Don Garrett86881cb2017-02-15 15:41:55 -080019from chromite.lib import osutils
Don Garrett0c54ed72017-03-03 11:18:57 -080020from chromite.scripts import cbuildbot_launch
Don Garrett86881cb2017-02-15 15:41:55 -080021
Don Garrett86881cb2017-02-15 15:41:55 -080022EXPECTED_MANIFEST_URL = 'https://chrome-internal-review.googlesource.com/chromeos/manifest-internal' # pylint: disable=line-too-long
Don Garrettc4114cc2016-11-01 20:04:06 -070023
24
Don Garrettacbb2392017-05-11 18:27:41 -070025# It's reasonable for unittests to look at internals.
26# pylint: disable=protected-access
27
28
Don Garrett8d314792017-05-18 13:11:42 -070029class FakeException(Exception):
30 """Test exception to raise during tests."""
31
32
Don Garrett0c54ed72017-03-03 11:18:57 -080033class CbuildbotLaunchTest(cros_test_lib.MockTestCase):
34 """Tests for cbuildbot_launch script."""
Don Garrettc4114cc2016-11-01 20:04:06 -070035
Don Garrett86881cb2017-02-15 15:41:55 -080036 def testPreParseArguments(self):
Don Garrettc4114cc2016-11-01 20:04:06 -070037 """Test that we can correctly extract branch values from cbuildbot args."""
Don Garrett597ddff2017-02-17 18:29:37 -080038 CASES = (
39 (['--buildroot', '/buildroot', 'daisy-incremental'],
40 (None, '/buildroot', None)),
41
42 (['--buildbot', '--buildroot', '/buildroot',
43 '--git-cache-dir', '/git-cache',
44 '-b', 'release-R57-9202.B',
45 'daisy-incremental'],
46 ('release-R57-9202.B', '/buildroot', '/git-cache')),
47
48 (['--debug', '--buildbot', '--notests',
49 '--buildroot', '/buildroot',
50 '--git-cache-dir', '/git-cache',
51 '--branch', 'release-R57-9202.B',
52 'daisy-incremental'],
53 ('release-R57-9202.B', '/buildroot', '/git-cache')),
Don Garrettc4114cc2016-11-01 20:04:06 -070054 )
55
Don Garrett597ddff2017-02-17 18:29:37 -080056 for cmd_args, expected in CASES:
57 expected_branch, expected_buildroot, expected_cache_dir = expected
58
Don Garrett0c54ed72017-03-03 11:18:57 -080059 options = cbuildbot_launch.PreParseArguments(cmd_args)
Don Garrett597ddff2017-02-17 18:29:37 -080060
61 self.assertEqual(options.branch, expected_branch)
62 self.assertEqual(options.buildroot, expected_buildroot)
63 self.assertEqual(options.git_cache_dir, expected_cache_dir)
Don Garrett86881cb2017-02-15 15:41:55 -080064
Don Garrettf324bc32017-05-23 14:00:53 -070065 def testInitialCheckout(self):
Don Garrett86881cb2017-02-15 15:41:55 -080066 """Test InitialCheckout with minimum settings."""
Don Garrettf324bc32017-05-23 14:00:53 -070067 mock_repo = mock.MagicMock()
68 mock_repo.branch = 'branch'
Don Garrett86881cb2017-02-15 15:41:55 -080069
Don Garrettf324bc32017-05-23 14:00:53 -070070 cbuildbot_launch.InitialCheckout(mock_repo)
Don Garrett86881cb2017-02-15 15:41:55 -080071
72 self.assertEqual(mock_repo.mock_calls, [
Don Garrettf324bc32017-05-23 14:00:53 -070073 mock.call.Sync(detach=True),
Don Garrett8d314792017-05-18 13:11:42 -070074 ])
75
Don Garrettf15d65b2017-04-12 12:39:55 -070076 def testConfigureGlobalEnvironment(self):
Don Garrett60967922017-04-12 18:51:44 -070077 """Ensure that we can setup our global runtime environment correctly."""
Don Garrett86fec482017-05-17 18:13:33 -070078
79 os.environ.pop('LANG', None)
80 os.environ['LC_MONETARY'] = 'bad'
81
Don Garrettf15d65b2017-04-12 12:39:55 -070082 cbuildbot_launch.ConfigureGlobalEnvironment()
83
Don Garrett86fec482017-05-17 18:13:33 -070084 # Verify umask is updated.
Don Garrettf15d65b2017-04-12 12:39:55 -070085 self.assertEqual(os.umask(0), 0o22)
86
Don Garrett86fec482017-05-17 18:13:33 -070087 # Verify ENVs are cleaned up.
88 self.assertEqual(os.environ['LANG'], 'en_US.UTF-8')
89 self.assertNotIn('LC_MONETARY', os.environ)
90
Don Garrettf15d65b2017-04-12 12:39:55 -070091
Benjamin Gordon121a2aa2018-05-04 16:24:45 -060092class RunDepotToolsEnsureBootstrap(cros_test_lib.RunCommandTestCase,
Don Garrett066e6f52017-09-28 19:14:01 -070093 cros_test_lib.TempDirTestCase):
94 """Test the helper function DepotToolsEnsureBootstrap."""
95
96 def testEnsureBootstrap(self):
97 """Verify that the script is run if present."""
98 script = os.path.join(self.tempdir, 'ensure_bootstrap')
99 osutils.Touch(script, makedirs=True)
100
101 cbuildbot_launch.DepotToolsEnsureBootstrap(self.tempdir)
102 self.assertCommandCalled(
103 [script], extra_env={'PATH': mock.ANY}, cwd=self.tempdir)
104
105 def testEnsureBootstrapMissing(self):
106 """Verify that the script is NOT run if not present."""
107 cbuildbot_launch.DepotToolsEnsureBootstrap(self.tempdir)
108 self.assertEqual(self.rc.call_count, 0)
109
110
Benjamin Gordon121a2aa2018-05-04 16:24:45 -0600111class RunTests(cros_test_lib.RunCommandTestCase):
Don Garrett0c54ed72017-03-03 11:18:57 -0800112 """Tests for cbuildbot_launch script."""
Don Garrett597ddff2017-02-17 18:29:37 -0800113
114 ARGS_BASE = ['--buildroot', '/buildroot']
Don Garrett5cd946b2017-07-20 13:42:20 -0700115 EXPECTED_ARGS_BASE = ['--buildroot', '/cbuildbot_buildroot']
Don Garrett597ddff2017-02-17 18:29:37 -0800116 ARGS_GIT_CACHE = ['--git-cache-dir', '/git-cache']
117 ARGS_CONFIG = ['config']
Don Garrettbf90cdf2017-05-19 15:54:02 -0700118 CMD = ['/cbuildbot_buildroot/chromite/bin/cbuildbot']
Don Garrett597ddff2017-02-17 18:29:37 -0800119
Don Garrett6e5c6b92018-04-06 17:58:49 -0700120 def verifyCbuildbot(self, args, expected_cmd, version):
Don Garrett86881cb2017-02-15 15:41:55 -0800121 """Ensure we invoke cbuildbot correctly."""
Don Garrett597ddff2017-02-17 18:29:37 -0800122 self.PatchObject(
123 cros_build_lib, 'GetTargetChromiteApiVersion', autospec=True,
124 return_value=version)
125
Don Garrett6e5c6b92018-04-06 17:58:49 -0700126 cbuildbot_launch.Cbuildbot('/cbuildbot_buildroot', '/depot_tools', args)
Don Garrett597ddff2017-02-17 18:29:37 -0800127
128 self.assertCommandCalled(
Don Garretta50bf492017-09-28 18:33:02 -0700129 expected_cmd, extra_env={'PATH': mock.ANY},
130 cwd='/cbuildbot_buildroot', error_code_ok=True)
Don Garrett597ddff2017-02-17 18:29:37 -0800131
Don Garrett6e5c6b92018-04-06 17:58:49 -0700132 def testCbuildbotSimple(self):
Don Garrett597ddff2017-02-17 18:29:37 -0800133 """Ensure we invoke cbuildbot correctly."""
Don Garrett6e5c6b92018-04-06 17:58:49 -0700134 self.verifyCbuildbot(
Don Garrett597ddff2017-02-17 18:29:37 -0800135 self.ARGS_BASE + self.ARGS_CONFIG,
Don Garrettbf90cdf2017-05-19 15:54:02 -0700136 self.CMD + self.ARGS_CONFIG + self.EXPECTED_ARGS_BASE,
Don Garrett597ddff2017-02-17 18:29:37 -0800137 (0, 4))
138
Don Garrett6e5c6b92018-04-06 17:58:49 -0700139 def testCbuildbotNotFiltered(self):
Don Garrett597ddff2017-02-17 18:29:37 -0800140 """Ensure we invoke cbuildbot correctly."""
Don Garrett6e5c6b92018-04-06 17:58:49 -0700141 self.verifyCbuildbot(
Don Garrett597ddff2017-02-17 18:29:37 -0800142 self.ARGS_BASE + self.ARGS_CONFIG + self.ARGS_GIT_CACHE,
Don Garrettbf90cdf2017-05-19 15:54:02 -0700143 (self.CMD + self.ARGS_CONFIG + self.EXPECTED_ARGS_BASE +
144 self.ARGS_GIT_CACHE),
Don Garrett597ddff2017-02-17 18:29:37 -0800145 (0, 4))
146
Don Garrett6e5c6b92018-04-06 17:58:49 -0700147 def testCbuildbotFiltered(self):
Don Garrett597ddff2017-02-17 18:29:37 -0800148 """Ensure we invoke cbuildbot correctly."""
Don Garrett6e5c6b92018-04-06 17:58:49 -0700149 self.verifyCbuildbot(
Don Garrett597ddff2017-02-17 18:29:37 -0800150 self.ARGS_BASE + self.ARGS_CONFIG + self.ARGS_GIT_CACHE,
Don Garrettbf90cdf2017-05-19 15:54:02 -0700151 self.CMD + self.ARGS_CONFIG + self.EXPECTED_ARGS_BASE,
Don Garrett597ddff2017-02-17 18:29:37 -0800152 (0, 2))
Don Garrettc4114cc2016-11-01 20:04:06 -0700153
Don Garrett86881cb2017-02-15 15:41:55 -0800154 def testMainMin(self):
155 """Test a minimal set of command line options."""
Don Garrett597ddff2017-02-17 18:29:37 -0800156 self.PatchObject(osutils, 'SafeMakedirs', autospec=True)
157 self.PatchObject(cros_build_lib, 'GetTargetChromiteApiVersion',
Don Garrett861e9182017-05-15 15:30:23 -0700158 autospec=True, return_value=(constants.REEXEC_API_MAJOR,
159 constants.REEXEC_API_MINOR))
Don Garrettf324bc32017-05-23 14:00:53 -0700160 mock_repo = mock.MagicMock()
161 mock_repo.branch = 'master'
Don Garrettbf90cdf2017-05-19 15:54:02 -0700162 mock_repo.directory = '/root/repository'
163
Don Garrettf324bc32017-05-23 14:00:53 -0700164 mock_repo_create = self.PatchObject(repository, 'RepoRepository',
165 autospec=True, return_value=mock_repo)
Don Garrettbf90cdf2017-05-19 15:54:02 -0700166 mock_clean = self.PatchObject(cbuildbot_launch, 'CleanBuildRoot',
Don Garrett0c54ed72017-03-03 11:18:57 -0800167 autospec=True)
168 mock_checkout = self.PatchObject(cbuildbot_launch, 'InitialCheckout',
Don Garrett86881cb2017-02-15 15:41:55 -0800169 autospec=True)
Benjamin Gordonaee36b82018-02-05 14:25:26 -0700170 mock_cleanup_chroot = self.PatchObject(cbuildbot_launch, 'CleanupChroot',
171 autospec=True)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600172 mock_set_last_build_state = self.PatchObject(
173 cbuildbot_launch, 'SetLastBuildState', autospec=True)
174
175 expected_build_state = build_summary.BuildSummary(
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600176 build_number=0, master_build_id=0, status=mock.ANY,
177 buildroot_layout=2, branch='master')
Don Garrett7ade05a2017-02-17 13:31:47 -0800178
Don Garrettbf90cdf2017-05-19 15:54:02 -0700179 cbuildbot_launch._main(['-r', '/root', 'config'])
Don Garrettc4114cc2016-11-01 20:04:06 -0700180
Don Garrettf324bc32017-05-23 14:00:53 -0700181 # Did we create the repo instance correctly?
182 self.assertEqual(mock_repo_create.mock_calls,
Don Garrettbf90cdf2017-05-19 15:54:02 -0700183 [mock.call(EXPECTED_MANIFEST_URL, '/root/repository',
Don Garrettf324bc32017-05-23 14:00:53 -0700184 git_cache_dir=None, branch='master')])
185
Don Garrett7ade05a2017-02-17 13:31:47 -0800186 # Ensure we clean, as expected.
Don Garrettbf90cdf2017-05-19 15:54:02 -0700187 self.assertEqual(mock_clean.mock_calls, [
Don Garrettd1d90dd2017-06-13 17:35:52 -0700188 mock.call('/root', mock_repo,
189 {
190 'branch_name': 'master',
191 'tryjob': False,
192 'build_config': 'config',
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600193 },
194 expected_build_state)])
Don Garrett7ade05a2017-02-17 13:31:47 -0800195
Don Garrett86881cb2017-02-15 15:41:55 -0800196 # Ensure we checkout, as expected.
197 self.assertEqual(mock_checkout.mock_calls,
Don Garrettf324bc32017-05-23 14:00:53 -0700198 [mock.call(mock_repo)])
Don Garrettc4114cc2016-11-01 20:04:06 -0700199
Don Garrett86881cb2017-02-15 15:41:55 -0800200 # Ensure we invoke cbuildbot, as expected.
201 self.assertCommandCalled(
Don Garrett5cd946b2017-07-20 13:42:20 -0700202 [
203 '/root/repository/chromite/bin/cbuildbot',
204 'config',
205 '-r', '/root/repository',
206 '--ts-mon-task-num', '1',
207 ],
Don Garretta50bf492017-09-28 18:33:02 -0700208 extra_env={'PATH': mock.ANY},
Don Garrettbf90cdf2017-05-19 15:54:02 -0700209 cwd='/root/repository',
Don Garrettacbb2392017-05-11 18:27:41 -0700210 error_code_ok=True)
Don Garrettc4114cc2016-11-01 20:04:06 -0700211
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600212 # Ensure we saved the final state, as expected.
213 self.assertEqual(expected_build_state.status,
214 constants.BUILDER_STATUS_PASSED)
215 self.assertEqual(mock_set_last_build_state.mock_calls, [
216 mock.call('/root', expected_build_state)])
217
Benjamin Gordonaee36b82018-02-05 14:25:26 -0700218 # Ensure we clean the chroot, as expected.
219 self.assertEqual(mock_cleanup_chroot.mock_calls, [
220 mock.call('/root/repository')])
221
Don Garrett86881cb2017-02-15 15:41:55 -0800222 def testMainMax(self):
Don Garrett597ddff2017-02-17 18:29:37 -0800223 """Test a larger set of command line options."""
224 self.PatchObject(osutils, 'SafeMakedirs', autospec=True)
225 self.PatchObject(cros_build_lib, 'GetTargetChromiteApiVersion',
Don Garrett861e9182017-05-15 15:30:23 -0700226 autospec=True, return_value=(constants.REEXEC_API_MAJOR,
227 constants.REEXEC_API_MINOR))
Don Garrettf324bc32017-05-23 14:00:53 -0700228 mock_repo = mock.MagicMock()
229 mock_repo.branch = 'branch'
Don Garrettbf90cdf2017-05-19 15:54:02 -0700230 mock_repo.directory = '/root/repository'
231
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600232 mock_summary = build_summary.BuildSummary(
233 build_number=313,
234 master_build_id=123123123,
235 status=constants.BUILDER_STATUS_FAILED,
236 buildroot_layout=cbuildbot_launch.BUILDROOT_BUILDROOT_LAYOUT,
237 branch='branch')
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600238
239 mock_get_last_build_state = self.PatchObject(
240 cbuildbot_launch, 'GetLastBuildState', autospec=True,
241 return_value=mock_summary)
Don Garrettf324bc32017-05-23 14:00:53 -0700242 mock_repo_create = self.PatchObject(repository, 'RepoRepository',
243 autospec=True, return_value=mock_repo)
Don Garrettbf90cdf2017-05-19 15:54:02 -0700244 mock_clean = self.PatchObject(cbuildbot_launch, 'CleanBuildRoot',
Don Garrett0c54ed72017-03-03 11:18:57 -0800245 autospec=True)
246 mock_checkout = self.PatchObject(cbuildbot_launch, 'InitialCheckout',
Don Garrett86881cb2017-02-15 15:41:55 -0800247 autospec=True)
Benjamin Gordonaee36b82018-02-05 14:25:26 -0700248 mock_cleanup_chroot = self.PatchObject(cbuildbot_launch, 'CleanupChroot',
249 autospec=True)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600250 mock_set_last_build_state = self.PatchObject(
251 cbuildbot_launch, 'SetLastBuildState', autospec=True)
Don Garrettc4114cc2016-11-01 20:04:06 -0700252
Don Garrettbf90cdf2017-05-19 15:54:02 -0700253 cbuildbot_launch._main(['--buildroot', '/root',
Don Garrettacbb2392017-05-11 18:27:41 -0700254 '--branch', 'branch',
255 '--git-cache-dir', '/git-cache',
Don Garrettd1d90dd2017-06-13 17:35:52 -0700256 '--remote-trybot',
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600257 '--master-build-id', '123456789',
258 '--buildnumber', '314',
Don Garrettacbb2392017-05-11 18:27:41 -0700259 'config'])
Don Garrettc4114cc2016-11-01 20:04:06 -0700260
Don Garrettf324bc32017-05-23 14:00:53 -0700261 # Did we create the repo instance correctly?
262 self.assertEqual(mock_repo_create.mock_calls,
Don Garrettbf90cdf2017-05-19 15:54:02 -0700263 [mock.call(EXPECTED_MANIFEST_URL, '/root/repository',
Don Garrettf324bc32017-05-23 14:00:53 -0700264 git_cache_dir='/git-cache', branch='branch')])
265
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600266 # Ensure we look up the previous status.
267 self.assertEqual(mock_get_last_build_state.mock_calls, [
268 mock.call('/root')])
269
Don Garrett7ade05a2017-02-17 13:31:47 -0800270 # Ensure we clean, as expected.
Don Garrettbf90cdf2017-05-19 15:54:02 -0700271 self.assertEqual(mock_clean.mock_calls, [
Don Garrettd1d90dd2017-06-13 17:35:52 -0700272 mock.call('/root',
273 mock_repo,
274 {
275 'branch_name': 'branch',
276 'tryjob': True,
277 'build_config': 'config',
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600278 },
279 build_summary.BuildSummary(
280 build_number=314,
281 master_build_id=123456789,
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600282 status=mock.ANY,
283 branch='branch',
284 buildroot_layout=2
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600285 ))])
Don Garrett7ade05a2017-02-17 13:31:47 -0800286
Don Garrett86881cb2017-02-15 15:41:55 -0800287 # Ensure we checkout, as expected.
288 self.assertEqual(mock_checkout.mock_calls,
Don Garrettf324bc32017-05-23 14:00:53 -0700289 [mock.call(mock_repo)])
Don Garrett86881cb2017-02-15 15:41:55 -0800290
291 # Ensure we invoke cbuildbot, as expected.
292 self.assertCommandCalled(
Don Garrett5cd946b2017-07-20 13:42:20 -0700293 [
294 '/root/repository/chromite/bin/cbuildbot',
295 'config',
296 '--buildroot', '/root/repository',
297 '--branch', 'branch',
298 '--git-cache-dir', '/git-cache',
299 '--remote-trybot',
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600300 '--master-build-id', '123456789',
301 '--buildnumber', '314',
302 '--previous-build-state',
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600303 'eyJzdGF0dXMiOiAiZmFpbCIsICJtYXN0ZXJfYnVpbGRfaWQiOiAxMjMxMjMxMj'
304 'MsICJidWlsZF9udW1iZXIiOiAzMTMsICJidWlsZHJvb3RfbGF5b3V0IjogMiwg'
305 'ImJyYW5jaCI6ICJicmFuY2gifQ==',
Don Garrett5cd946b2017-07-20 13:42:20 -0700306 '--ts-mon-task-num', '1',
307 ],
Don Garretta50bf492017-09-28 18:33:02 -0700308 extra_env={'PATH': mock.ANY},
Don Garrettbf90cdf2017-05-19 15:54:02 -0700309 cwd='/root/repository',
Don Garrettacbb2392017-05-11 18:27:41 -0700310 error_code_ok=True)
Don Garrett7ade05a2017-02-17 13:31:47 -0800311
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600312 # Ensure we write the final build state, as expected.
313 final_state = build_summary.BuildSummary(
314 build_number=314,
315 master_build_id=123456789,
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600316 status=constants.BUILDER_STATUS_PASSED,
317 buildroot_layout=2,
318 branch='branch')
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600319 self.assertEqual(mock_set_last_build_state.mock_calls, [
320 mock.call('/root', final_state)])
321
Benjamin Gordonaee36b82018-02-05 14:25:26 -0700322 # Ensure we clean the chroot, as expected.
323 self.assertEqual(mock_cleanup_chroot.mock_calls, [
324 mock.call('/root/repository')])
325
Don Garrett7ade05a2017-02-17 13:31:47 -0800326
Don Garrettbf90cdf2017-05-19 15:54:02 -0700327class CleanBuildRootTest(cros_test_lib.MockTempDirTestCase):
328 """Tests for CleanBuildRoot method."""
Don Garrett7ade05a2017-02-17 13:31:47 -0800329
330 def setUp(self):
331 """Create standard buildroot contents for cleanup."""
Don Garrettbf90cdf2017-05-19 15:54:02 -0700332 self.root = os.path.join(self.tempdir)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600333 self.previous_build_state = os.path.join(
334 self.root, '.cbuildbot_build_state.json')
Don Garrettbf90cdf2017-05-19 15:54:02 -0700335 self.buildroot = os.path.join(self.root, 'buildroot')
336 self.repo = os.path.join(self.buildroot, '.repo/repo')
337 self.chroot = os.path.join(self.buildroot, 'chroot/chroot')
338 self.general = os.path.join(self.buildroot, 'general/general')
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700339 self.cache = os.path.join(self.buildroot, '.cache')
340 self.distfiles = os.path.join(self.cache, 'distfiles')
Don Garrett7ade05a2017-02-17 13:31:47 -0800341
Don Garrettf324bc32017-05-23 14:00:53 -0700342 self.mock_repo = mock.MagicMock()
Don Garrettbf90cdf2017-05-19 15:54:02 -0700343 self.mock_repo.directory = self.buildroot
Don Garrettf324bc32017-05-23 14:00:53 -0700344
Don Garrettacbb2392017-05-11 18:27:41 -0700345 self.metrics = {}
346
Benjamin Gordon8642bcc2018-05-01 13:49:56 -0600347 def populateBuildroot(self, previous_build_state=None):
Don Garrett7ade05a2017-02-17 13:31:47 -0800348 """Create standard buildroot contents for cleanup."""
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600349 if previous_build_state:
350 osutils.SafeMakedirs(self.root)
351 osutils.WriteFile(self.previous_build_state, previous_build_state)
352
Don Garrett7ade05a2017-02-17 13:31:47 -0800353 # Create files.
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700354 for f in (self.repo, self.chroot, self.general, self.distfiles):
Don Garrette17e1d92017-04-12 15:28:19 -0700355 osutils.Touch(f, makedirs=True)
Don Garrett7ade05a2017-02-17 13:31:47 -0800356
Don Garrette17e1d92017-04-12 15:28:19 -0700357 def testNoBuildroot(self):
Don Garrettbf90cdf2017-05-19 15:54:02 -0700358 """Test CleanBuildRoot with no history."""
Don Garrettf324bc32017-05-23 14:00:53 -0700359 self.mock_repo.branch = 'master'
360
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600361 build_state = build_summary.BuildSummary(
362 status=constants.BUILDER_STATUS_INFLIGHT,
363 buildroot_layout=cbuildbot_launch.BUILDROOT_BUILDROOT_LAYOUT,
364 branch='master')
Don Garrettbf90cdf2017-05-19 15:54:02 -0700365 cbuildbot_launch.CleanBuildRoot(
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600366 self.root, self.mock_repo, self.metrics, build_state)
Don Garrett7ade05a2017-02-17 13:31:47 -0800367
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600368 new_summary = cbuildbot_launch.GetLastBuildState(self.root)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600369 self.assertEqual(new_summary.buildroot_layout, 2)
370 self.assertEqual(new_summary.branch, 'master')
371 self.assertIsNotNone(new_summary.distfiles_ts)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600372 self.assertEqual(new_summary, build_state)
Don Garrett7ade05a2017-02-17 13:31:47 -0800373
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600374 self.assertExists(self.previous_build_state)
375
Don Garrett7ade05a2017-02-17 13:31:47 -0800376 def testBuildrootNoState(self):
Don Garrettbf90cdf2017-05-19 15:54:02 -0700377 """Test CleanBuildRoot with no state information."""
Don Garrett7ade05a2017-02-17 13:31:47 -0800378 self.populateBuildroot()
Don Garrettf324bc32017-05-23 14:00:53 -0700379 self.mock_repo.branch = 'master'
Don Garrett7ade05a2017-02-17 13:31:47 -0800380
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600381 build_state = build_summary.BuildSummary(
382 status=constants.BUILDER_STATUS_INFLIGHT,
383 buildroot_layout=cbuildbot_launch.BUILDROOT_BUILDROOT_LAYOUT,
384 branch='master')
Don Garrettbf90cdf2017-05-19 15:54:02 -0700385 cbuildbot_launch.CleanBuildRoot(
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600386 self.root, self.mock_repo, self.metrics, build_state)
Don Garrett7ade05a2017-02-17 13:31:47 -0800387
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600388 new_summary = cbuildbot_launch.GetLastBuildState(self.root)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600389 self.assertEqual(new_summary.buildroot_layout, 2)
390 self.assertEqual(new_summary.branch, 'master')
391 self.assertIsNotNone(new_summary.distfiles_ts)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600392 self.assertEqual(new_summary, build_state)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700393
Don Garrett60967922017-04-12 18:51:44 -0700394 self.assertNotExists(self.repo)
Don Garrett7ade05a2017-02-17 13:31:47 -0800395 self.assertNotExists(self.chroot)
Don Garrett60967922017-04-12 18:51:44 -0700396 self.assertNotExists(self.general)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700397 self.assertNotExists(self.distfiles)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600398 self.assertExists(self.previous_build_state)
Don Garrett7ade05a2017-02-17 13:31:47 -0800399
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600400 def testBuildrootFormatMismatch(self):
401 """Test CleanBuildRoot with buildroot layout mismatch."""
402 old_build_state = build_summary.BuildSummary(
403 status=constants.BUILDER_STATUS_PASSED,
404 buildroot_layout=1,
405 branch='master')
406 self.populateBuildroot(previous_build_state=old_build_state.to_json())
407 self.mock_repo.branch = 'master'
408
409 build_state = build_summary.BuildSummary(
410 status=constants.BUILDER_STATUS_INFLIGHT,
411 buildroot_layout=cbuildbot_launch.BUILDROOT_BUILDROOT_LAYOUT,
412 branch='master')
413 cbuildbot_launch.CleanBuildRoot(
414 self.root, self.mock_repo, self.metrics, build_state)
415
416 new_summary = cbuildbot_launch.GetLastBuildState(self.root)
417 self.assertEqual(new_summary.buildroot_layout, 2)
418 self.assertEqual(new_summary.branch, 'master')
419 self.assertIsNotNone(new_summary.distfiles_ts)
420 self.assertEqual(new_summary, build_state)
421
422 self.assertNotExists(self.repo)
423 self.assertNotExists(self.chroot)
424 self.assertNotExists(self.general)
425 self.assertNotExists(self.distfiles)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600426 self.assertExists(self.previous_build_state)
427
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600428 def testBuildrootBranchChange(self):
429 """Test CleanBuildRoot with a change in branches."""
430 old_build_state = build_summary.BuildSummary(
431 status=constants.BUILDER_STATUS_PASSED,
432 buildroot_layout=2,
433 branch='branchA')
434 self.populateBuildroot(previous_build_state=old_build_state.to_json())
435 self.mock_repo.branch = 'branchB'
436 m = self.PatchObject(cros_build_lib, 'CleanupChrootMount')
Don Garrett7ade05a2017-02-17 13:31:47 -0800437
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600438 build_state = build_summary.BuildSummary(
439 status=constants.BUILDER_STATUS_INFLIGHT,
440 buildroot_layout=cbuildbot_launch.BUILDROOT_BUILDROOT_LAYOUT,
441 branch='branchB')
Don Garrettbf90cdf2017-05-19 15:54:02 -0700442 cbuildbot_launch.CleanBuildRoot(
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600443 self.root, self.mock_repo, self.metrics, build_state)
Don Garrett7ade05a2017-02-17 13:31:47 -0800444
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600445 new_summary = cbuildbot_launch.GetLastBuildState(self.root)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600446 self.assertEqual(new_summary.buildroot_layout, 2)
447 self.assertEqual(new_summary.branch, 'branchB')
448 self.assertIsNotNone(new_summary.distfiles_ts)
449 self.assertEqual(new_summary, build_state)
450
451 self.assertExists(self.repo)
452 self.assertNotExists(self.chroot)
453 self.assertExists(self.general)
454 self.assertNotExists(self.distfiles)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600455 self.assertExists(self.previous_build_state)
456 m.assert_called()
457
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600458 def testBuildrootBranchMatch(self):
459 """Test CleanBuildRoot with no change in branch."""
460 old_build_state = build_summary.BuildSummary(
461 status=constants.BUILDER_STATUS_PASSED,
462 buildroot_layout=2,
463 branch='branchA')
464 self.populateBuildroot(previous_build_state=old_build_state.to_json())
465 self.mock_repo.branch = 'branchA'
466
467 build_state = build_summary.BuildSummary(
468 status=constants.BUILDER_STATUS_INFLIGHT,
469 buildroot_layout=cbuildbot_launch.BUILDROOT_BUILDROOT_LAYOUT,
470 branch='branchA')
471 cbuildbot_launch.CleanBuildRoot(
472 self.root, self.mock_repo, self.metrics, build_state)
473
474 new_summary = cbuildbot_launch.GetLastBuildState(self.root)
475 self.assertEqual(new_summary.buildroot_layout, 2)
476 self.assertEqual(new_summary.branch, 'branchA')
477 self.assertIsNotNone(new_summary.distfiles_ts)
478 self.assertEqual(new_summary, build_state)
479
480 self.assertExists(self.repo)
481 self.assertExists(self.chroot)
482 self.assertExists(self.general)
483 self.assertExists(self.distfiles)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600484 self.assertExists(self.previous_build_state)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700485
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600486 def testBuildrootDistfilesRecentCache(self):
487 """Test CleanBuildRoot does not delete distfiles when cache is recent."""
488 seed_distfiles_ts = time.time() - 60
489 old_build_state = build_summary.BuildSummary(
490 status=constants.BUILDER_STATUS_PASSED,
491 buildroot_layout=2,
492 branch='branchA',
493 distfiles_ts=seed_distfiles_ts)
494 self.populateBuildroot(previous_build_state=old_build_state.to_json())
495 self.mock_repo.branch = 'branchA'
496
497 build_state = build_summary.BuildSummary(
498 status=constants.BUILDER_STATUS_INFLIGHT,
499 buildroot_layout=cbuildbot_launch.BUILDROOT_BUILDROOT_LAYOUT,
500 branch='branchA')
501 cbuildbot_launch.CleanBuildRoot(
502 self.root, self.mock_repo, self.metrics, build_state)
503
504 new_summary = cbuildbot_launch.GetLastBuildState(self.root)
505 self.assertEqual(new_summary.buildroot_layout, 2)
506 self.assertEqual(new_summary.branch, 'branchA')
507 # Same cache creation timestamp is rewritten to state.
508 self.assertEqual(new_summary.distfiles_ts, seed_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)
Don Garrette17e1d92017-04-12 15:28:19 -0700516
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600517 def testBuildrootDistfilesCacheExpired(self):
518 """Test CleanBuildRoot when the distfiles cache is too old."""
519 old_build_state = build_summary.BuildSummary(
520 status=constants.BUILDER_STATUS_PASSED,
521 buildroot_layout=2,
522 branch='branchA',
523 distfiles_ts=100.0)
524 self.populateBuildroot(previous_build_state=old_build_state.to_json())
525 self.mock_repo.branch = 'branchA'
526
527 build_state = build_summary.BuildSummary(
528 status=constants.BUILDER_STATUS_INFLIGHT,
529 buildroot_layout=cbuildbot_launch.BUILDROOT_BUILDROOT_LAYOUT,
530 branch='branchA')
531 cbuildbot_launch.CleanBuildRoot(
532 self.root, self.mock_repo, self.metrics, build_state)
533
534 new_summary = cbuildbot_launch.GetLastBuildState(self.root)
535 self.assertEqual(new_summary.buildroot_layout, 2)
536 self.assertEqual(new_summary.branch, 'branchA')
537 self.assertIsNotNone(new_summary.distfiles_ts)
538 self.assertEqual(new_summary, build_state)
539
540 self.assertExists(self.repo)
541 self.assertExists(self.chroot)
542 self.assertExists(self.general)
543 self.assertNotExists(self.distfiles)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600544 self.assertExists(self.previous_build_state)
545
546 def testBuildrootRepoCleanFailure(self):
547 """Test CleanBuildRoot with repo checkout failure."""
548 old_build_state = build_summary.BuildSummary(
549 status=constants.BUILDER_STATUS_PASSED,
550 buildroot_layout=1,
551 branch='branchA')
552 self.populateBuildroot(previous_build_state=old_build_state.to_json())
553 self.mock_repo.branch = 'branchA'
554 self.mock_repo.BuildRootGitCleanup.side_effect = Exception
555
556 build_state = build_summary.BuildSummary(
557 status=constants.BUILDER_STATUS_INFLIGHT,
558 buildroot_layout=cbuildbot_launch.BUILDROOT_BUILDROOT_LAYOUT,
559 branch='branchA')
560 cbuildbot_launch.CleanBuildRoot(
561 self.root, self.mock_repo, self.metrics, build_state)
562
563 new_summary = cbuildbot_launch.GetLastBuildState(self.root)
564 self.assertEqual(new_summary.buildroot_layout, 2)
565 self.assertEqual(new_summary.branch, 'branchA')
566 self.assertIsNotNone(new_summary.distfiles_ts)
567 self.assertEqual(new_summary, build_state)
568
569 self.assertNotExists(self.repo)
570 self.assertNotExists(self.chroot)
571 self.assertNotExists(self.general)
572 self.assertNotExists(self.distfiles)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600573 self.assertExists(self.previous_build_state)
Don Garrettf324bc32017-05-23 14:00:53 -0700574
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600575 def testGetCurrentBuildStateNoArgs(self):
576 """Tests GetCurrentBuildState without arguments."""
577 options = cbuildbot_launch.PreParseArguments([
578 '--buildroot', self.root, 'config'
579 ])
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600580 state = cbuildbot_launch.GetCurrentBuildState(options, 'master')
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600581
582 expected_state = build_summary.BuildSummary(
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600583 status=constants.BUILDER_STATUS_INFLIGHT,
584 buildroot_layout=2,
585 branch='master')
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600586 self.assertEqual(state, expected_state)
587
588 def testGetCurrentBuildStateHasArgs(self):
589 """Tests GetCurrentBuildState with arguments."""
590 options = cbuildbot_launch.PreParseArguments([
591 '--buildroot', self.root,
592 '--buildnumber', '20',
593 '--master-build-id', '50',
594 'config'
595 ])
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600596 state = cbuildbot_launch.GetCurrentBuildState(options, 'branchA')
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600597
598 expected_state = build_summary.BuildSummary(
599 build_number=20,
600 master_build_id=50,
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600601 status=constants.BUILDER_STATUS_INFLIGHT,
602 buildroot_layout=2,
603 branch='branchA')
604 self.assertEqual(state, expected_state)
605
606 def testGetCurrentBuildStateLayout(self):
607 """Test that GetCurrentBuildState uses the current buildroot layout."""
608 # Change to a future version.
609 self.PatchObject(cbuildbot_launch, 'BUILDROOT_BUILDROOT_LAYOUT', 22)
610
611 options = cbuildbot_launch.PreParseArguments([
612 '--buildroot', self.root, 'config'
613 ])
614 state = cbuildbot_launch.GetCurrentBuildState(options, 'branchA')
615
616 expected_state = build_summary.BuildSummary(
617 status=constants.BUILDER_STATUS_INFLIGHT,
618 buildroot_layout=22,
619 branch='branchA')
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600620 self.assertEqual(state, expected_state)
621
622 def testGetLastBuildStateNoFile(self):
623 """Tests GetLastBuildState if the file is missing."""
624 osutils.SafeMakedirs(self.root)
625 state = cbuildbot_launch.GetLastBuildState(self.root)
626 self.assertEqual(state, build_summary.BuildSummary())
627
628 def testGetLastBuildStateBadFile(self):
629 """Tests GetLastBuildState if the file contains invalid JSON."""
630 osutils.SafeMakedirs(self.root)
631 osutils.WriteFile(self.previous_build_state, '}}')
632 state = cbuildbot_launch.GetLastBuildState(self.root)
633 self.assertEqual(state, build_summary.BuildSummary())
634
635 def testGetLastBuildStateMissingBuildStatus(self):
636 """Tests GetLastBuildState if the file doesn't have a valid status."""
637 osutils.SafeMakedirs(self.root)
638 osutils.WriteFile(self.previous_build_state, '{"build_number": "3"}')
639 state = cbuildbot_launch.GetLastBuildState(self.root)
640 self.assertEqual(state, build_summary.BuildSummary())
641
642 def testGetLastBuildStateGoodFile(self):
643 """Tests GetLastBuildState on a good file."""
644 osutils.SafeMakedirs(self.root)
645 osutils.WriteFile(
646 self.previous_build_state,
647 '{"build_number": 1, "master_build_id": 3, "status": "pass"}')
648 state = cbuildbot_launch.GetLastBuildState(self.root)
649 self.assertEqual(
650 state,
651 build_summary.BuildSummary(
652 build_number=1, master_build_id=3, status='pass'))
653
654 def testSetLastBuildState(self):
655 """Verifies that SetLastBuildState writes to the expected file."""
656 osutils.SafeMakedirs(self.root)
657 old_state = build_summary.BuildSummary(
658 build_number=314,
659 master_build_id=2178,
660 status=constants.BUILDER_STATUS_PASSED)
661 cbuildbot_launch.SetLastBuildState(self.root, old_state)
662
663 saved_state = osutils.ReadFile(self.previous_build_state)
664 new_state = build_summary.BuildSummary()
665 new_state.from_json(saved_state)
666
667 self.assertEqual(old_state, new_state)