blob: f1f21853d5c9d5cf44cfaac43b3f7d522fac6b23 [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 RunDepotToolsEnsureBootstrap(cros_test_lib.RunCommandTestCase,
Don Garrett066e6f52017-09-28 19:14:01 -070094 cros_test_lib.TempDirTestCase):
95 """Test the helper function DepotToolsEnsureBootstrap."""
96
97 def testEnsureBootstrap(self):
98 """Verify that the script is run if present."""
99 script = os.path.join(self.tempdir, 'ensure_bootstrap')
100 osutils.Touch(script, makedirs=True)
101
102 cbuildbot_launch.DepotToolsEnsureBootstrap(self.tempdir)
103 self.assertCommandCalled(
104 [script], extra_env={'PATH': mock.ANY}, cwd=self.tempdir)
105
106 def testEnsureBootstrapMissing(self):
107 """Verify that the script is NOT run if not present."""
108 cbuildbot_launch.DepotToolsEnsureBootstrap(self.tempdir)
109 self.assertEqual(self.rc.call_count, 0)
110
111
Benjamin Gordon121a2aa2018-05-04 16:24:45 -0600112class RunTests(cros_test_lib.RunCommandTestCase):
Don Garrett0c54ed72017-03-03 11:18:57 -0800113 """Tests for cbuildbot_launch script."""
Don Garrett597ddff2017-02-17 18:29:37 -0800114
115 ARGS_BASE = ['--buildroot', '/buildroot']
Don Garrett5cd946b2017-07-20 13:42:20 -0700116 EXPECTED_ARGS_BASE = ['--buildroot', '/cbuildbot_buildroot']
Don Garrett597ddff2017-02-17 18:29:37 -0800117 ARGS_GIT_CACHE = ['--git-cache-dir', '/git-cache']
118 ARGS_CONFIG = ['config']
Don Garrettbf90cdf2017-05-19 15:54:02 -0700119 CMD = ['/cbuildbot_buildroot/chromite/bin/cbuildbot']
Don Garrett597ddff2017-02-17 18:29:37 -0800120
Don Garrett6e5c6b92018-04-06 17:58:49 -0700121 def verifyCbuildbot(self, args, expected_cmd, version):
Don Garrett86881cb2017-02-15 15:41:55 -0800122 """Ensure we invoke cbuildbot correctly."""
Don Garrett597ddff2017-02-17 18:29:37 -0800123 self.PatchObject(
124 cros_build_lib, 'GetTargetChromiteApiVersion', autospec=True,
125 return_value=version)
126
Don Garrett6e5c6b92018-04-06 17:58:49 -0700127 cbuildbot_launch.Cbuildbot('/cbuildbot_buildroot', '/depot_tools', args)
Don Garrett597ddff2017-02-17 18:29:37 -0800128
129 self.assertCommandCalled(
Don Garretta50bf492017-09-28 18:33:02 -0700130 expected_cmd, extra_env={'PATH': mock.ANY},
131 cwd='/cbuildbot_buildroot', error_code_ok=True)
Don Garrett597ddff2017-02-17 18:29:37 -0800132
Don Garrett6e5c6b92018-04-06 17:58:49 -0700133 def testCbuildbotSimple(self):
Don Garrett597ddff2017-02-17 18:29:37 -0800134 """Ensure we invoke cbuildbot correctly."""
Don Garrett6e5c6b92018-04-06 17:58:49 -0700135 self.verifyCbuildbot(
Don Garrett597ddff2017-02-17 18:29:37 -0800136 self.ARGS_BASE + self.ARGS_CONFIG,
Don Garrettbf90cdf2017-05-19 15:54:02 -0700137 self.CMD + self.ARGS_CONFIG + self.EXPECTED_ARGS_BASE,
Don Garrett597ddff2017-02-17 18:29:37 -0800138 (0, 4))
139
Don Garrett6e5c6b92018-04-06 17:58:49 -0700140 def testCbuildbotNotFiltered(self):
Don Garrett597ddff2017-02-17 18:29:37 -0800141 """Ensure we invoke cbuildbot correctly."""
Don Garrett6e5c6b92018-04-06 17:58:49 -0700142 self.verifyCbuildbot(
Don Garrett597ddff2017-02-17 18:29:37 -0800143 self.ARGS_BASE + self.ARGS_CONFIG + self.ARGS_GIT_CACHE,
Don Garrettbf90cdf2017-05-19 15:54:02 -0700144 (self.CMD + self.ARGS_CONFIG + self.EXPECTED_ARGS_BASE +
145 self.ARGS_GIT_CACHE),
Don Garrett597ddff2017-02-17 18:29:37 -0800146 (0, 4))
147
Don Garrett6e5c6b92018-04-06 17:58:49 -0700148 def testCbuildbotFiltered(self):
Don Garrett597ddff2017-02-17 18:29:37 -0800149 """Ensure we invoke cbuildbot correctly."""
Don Garrett6e5c6b92018-04-06 17:58:49 -0700150 self.verifyCbuildbot(
Don Garrett597ddff2017-02-17 18:29:37 -0800151 self.ARGS_BASE + self.ARGS_CONFIG + self.ARGS_GIT_CACHE,
Don Garrettbf90cdf2017-05-19 15:54:02 -0700152 self.CMD + self.ARGS_CONFIG + self.EXPECTED_ARGS_BASE,
Don Garrett597ddff2017-02-17 18:29:37 -0800153 (0, 2))
Don Garrettc4114cc2016-11-01 20:04:06 -0700154
Don Garrett86881cb2017-02-15 15:41:55 -0800155 def testMainMin(self):
156 """Test a minimal set of command line options."""
Don Garrett597ddff2017-02-17 18:29:37 -0800157 self.PatchObject(osutils, 'SafeMakedirs', autospec=True)
158 self.PatchObject(cros_build_lib, 'GetTargetChromiteApiVersion',
Don Garrett861e9182017-05-15 15:30:23 -0700159 autospec=True, return_value=(constants.REEXEC_API_MAJOR,
160 constants.REEXEC_API_MINOR))
Don Garrettf324bc32017-05-23 14:00:53 -0700161 mock_repo = mock.MagicMock()
162 mock_repo.branch = 'master'
Don Garrettbf90cdf2017-05-19 15:54:02 -0700163 mock_repo.directory = '/root/repository'
164
Don Garrettf324bc32017-05-23 14:00:53 -0700165 mock_repo_create = self.PatchObject(repository, 'RepoRepository',
166 autospec=True, return_value=mock_repo)
Don Garrettbf90cdf2017-05-19 15:54:02 -0700167 mock_clean = self.PatchObject(cbuildbot_launch, 'CleanBuildRoot',
Don Garrett0c54ed72017-03-03 11:18:57 -0800168 autospec=True)
169 mock_checkout = self.PatchObject(cbuildbot_launch, 'InitialCheckout',
Don Garrett86881cb2017-02-15 15:41:55 -0800170 autospec=True)
Benjamin Gordonaee36b82018-02-05 14:25:26 -0700171 mock_cleanup_chroot = self.PatchObject(cbuildbot_launch, 'CleanupChroot',
172 autospec=True)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600173 mock_set_last_build_state = self.PatchObject(
174 cbuildbot_launch, 'SetLastBuildState', autospec=True)
175
176 expected_build_state = build_summary.BuildSummary(
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600177 build_number=0, master_build_id=0, status=mock.ANY,
178 buildroot_layout=2, branch='master')
Don Garrett7ade05a2017-02-17 13:31:47 -0800179
Don Garrettbf90cdf2017-05-19 15:54:02 -0700180 cbuildbot_launch._main(['-r', '/root', 'config'])
Don Garrettc4114cc2016-11-01 20:04:06 -0700181
Don Garrettf324bc32017-05-23 14:00:53 -0700182 # Did we create the repo instance correctly?
183 self.assertEqual(mock_repo_create.mock_calls,
Don Garrettbf90cdf2017-05-19 15:54:02 -0700184 [mock.call(EXPECTED_MANIFEST_URL, '/root/repository',
Don Garrettf324bc32017-05-23 14:00:53 -0700185 git_cache_dir=None, branch='master')])
186
Don Garrett7ade05a2017-02-17 13:31:47 -0800187 # Ensure we clean, as expected.
Don Garrettbf90cdf2017-05-19 15:54:02 -0700188 self.assertEqual(mock_clean.mock_calls, [
Don Garrettd1d90dd2017-06-13 17:35:52 -0700189 mock.call('/root', mock_repo,
190 {
191 'branch_name': 'master',
192 'tryjob': False,
193 'build_config': 'config',
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600194 },
195 expected_build_state)])
Don Garrett7ade05a2017-02-17 13:31:47 -0800196
Don Garrett86881cb2017-02-15 15:41:55 -0800197 # Ensure we checkout, as expected.
198 self.assertEqual(mock_checkout.mock_calls,
Don Garrettf324bc32017-05-23 14:00:53 -0700199 [mock.call(mock_repo)])
Don Garrettc4114cc2016-11-01 20:04:06 -0700200
Don Garrett86881cb2017-02-15 15:41:55 -0800201 # Ensure we invoke cbuildbot, as expected.
202 self.assertCommandCalled(
Don Garrett5cd946b2017-07-20 13:42:20 -0700203 [
204 '/root/repository/chromite/bin/cbuildbot',
205 'config',
206 '-r', '/root/repository',
Don Garrettb497f552018-07-09 16:01:13 -0700207 '--workspace', '/root/workspace',
Don Garrett5cd946b2017-07-20 13:42:20 -0700208 '--ts-mon-task-num', '1',
209 ],
Don Garretta50bf492017-09-28 18:33:02 -0700210 extra_env={'PATH': mock.ANY},
Don Garrettbf90cdf2017-05-19 15:54:02 -0700211 cwd='/root/repository',
Don Garrettacbb2392017-05-11 18:27:41 -0700212 error_code_ok=True)
Don Garrettc4114cc2016-11-01 20:04:06 -0700213
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600214 # Ensure we saved the final state, as expected.
215 self.assertEqual(expected_build_state.status,
216 constants.BUILDER_STATUS_PASSED)
217 self.assertEqual(mock_set_last_build_state.mock_calls, [
218 mock.call('/root', expected_build_state)])
219
Benjamin Gordonaee36b82018-02-05 14:25:26 -0700220 # Ensure we clean the chroot, as expected.
221 self.assertEqual(mock_cleanup_chroot.mock_calls, [
222 mock.call('/root/repository')])
223
Don Garrett86881cb2017-02-15 15:41:55 -0800224 def testMainMax(self):
Don Garrett597ddff2017-02-17 18:29:37 -0800225 """Test a larger set of command line options."""
226 self.PatchObject(osutils, 'SafeMakedirs', autospec=True)
227 self.PatchObject(cros_build_lib, 'GetTargetChromiteApiVersion',
Don Garrett861e9182017-05-15 15:30:23 -0700228 autospec=True, return_value=(constants.REEXEC_API_MAJOR,
229 constants.REEXEC_API_MINOR))
Don Garrettf324bc32017-05-23 14:00:53 -0700230 mock_repo = mock.MagicMock()
231 mock_repo.branch = 'branch'
Don Garrettbf90cdf2017-05-19 15:54:02 -0700232 mock_repo.directory = '/root/repository'
233
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600234 mock_summary = build_summary.BuildSummary(
235 build_number=313,
236 master_build_id=123123123,
237 status=constants.BUILDER_STATUS_FAILED,
238 buildroot_layout=cbuildbot_launch.BUILDROOT_BUILDROOT_LAYOUT,
239 branch='branch')
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600240
241 mock_get_last_build_state = self.PatchObject(
242 cbuildbot_launch, 'GetLastBuildState', autospec=True,
243 return_value=mock_summary)
Don Garrettf324bc32017-05-23 14:00:53 -0700244 mock_repo_create = self.PatchObject(repository, 'RepoRepository',
245 autospec=True, return_value=mock_repo)
Don Garrettbf90cdf2017-05-19 15:54:02 -0700246 mock_clean = self.PatchObject(cbuildbot_launch, 'CleanBuildRoot',
Don Garrett0c54ed72017-03-03 11:18:57 -0800247 autospec=True)
248 mock_checkout = self.PatchObject(cbuildbot_launch, 'InitialCheckout',
Don Garrett86881cb2017-02-15 15:41:55 -0800249 autospec=True)
Benjamin Gordonaee36b82018-02-05 14:25:26 -0700250 mock_cleanup_chroot = self.PatchObject(cbuildbot_launch, 'CleanupChroot',
251 autospec=True)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600252 mock_set_last_build_state = self.PatchObject(
253 cbuildbot_launch, 'SetLastBuildState', autospec=True)
Don Garrettc4114cc2016-11-01 20:04:06 -0700254
Don Garrettbf90cdf2017-05-19 15:54:02 -0700255 cbuildbot_launch._main(['--buildroot', '/root',
Don Garrettacbb2392017-05-11 18:27:41 -0700256 '--branch', 'branch',
257 '--git-cache-dir', '/git-cache',
Don Garrettd1d90dd2017-06-13 17:35:52 -0700258 '--remote-trybot',
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600259 '--master-build-id', '123456789',
260 '--buildnumber', '314',
Don Garrettacbb2392017-05-11 18:27:41 -0700261 'config'])
Don Garrettc4114cc2016-11-01 20:04:06 -0700262
Don Garrettf324bc32017-05-23 14:00:53 -0700263 # Did we create the repo instance correctly?
264 self.assertEqual(mock_repo_create.mock_calls,
Don Garrettbf90cdf2017-05-19 15:54:02 -0700265 [mock.call(EXPECTED_MANIFEST_URL, '/root/repository',
Don Garrettf324bc32017-05-23 14:00:53 -0700266 git_cache_dir='/git-cache', branch='branch')])
267
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600268 # Ensure we look up the previous status.
269 self.assertEqual(mock_get_last_build_state.mock_calls, [
270 mock.call('/root')])
271
Don Garrett7ade05a2017-02-17 13:31:47 -0800272 # Ensure we clean, as expected.
Don Garrettbf90cdf2017-05-19 15:54:02 -0700273 self.assertEqual(mock_clean.mock_calls, [
Don Garrettd1d90dd2017-06-13 17:35:52 -0700274 mock.call('/root',
275 mock_repo,
276 {
277 'branch_name': 'branch',
278 'tryjob': True,
279 'build_config': 'config',
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600280 },
281 build_summary.BuildSummary(
282 build_number=314,
283 master_build_id=123456789,
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600284 status=mock.ANY,
285 branch='branch',
286 buildroot_layout=2
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600287 ))])
Don Garrett7ade05a2017-02-17 13:31:47 -0800288
Don Garrett86881cb2017-02-15 15:41:55 -0800289 # Ensure we checkout, as expected.
290 self.assertEqual(mock_checkout.mock_calls,
Don Garrettf324bc32017-05-23 14:00:53 -0700291 [mock.call(mock_repo)])
Don Garrett86881cb2017-02-15 15:41:55 -0800292
293 # Ensure we invoke cbuildbot, as expected.
294 self.assertCommandCalled(
Don Garrett5cd946b2017-07-20 13:42:20 -0700295 [
296 '/root/repository/chromite/bin/cbuildbot',
297 'config',
298 '--buildroot', '/root/repository',
299 '--branch', 'branch',
300 '--git-cache-dir', '/git-cache',
301 '--remote-trybot',
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600302 '--master-build-id', '123456789',
303 '--buildnumber', '314',
304 '--previous-build-state',
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600305 'eyJzdGF0dXMiOiAiZmFpbCIsICJtYXN0ZXJfYnVpbGRfaWQiOiAxMjMxMjMxMj'
306 'MsICJidWlsZF9udW1iZXIiOiAzMTMsICJidWlsZHJvb3RfbGF5b3V0IjogMiwg'
307 'ImJyYW5jaCI6ICJicmFuY2gifQ==',
Don Garrettb497f552018-07-09 16:01:13 -0700308 '--workspace', '/root/workspace',
Don Garrett5cd946b2017-07-20 13:42:20 -0700309 '--ts-mon-task-num', '1',
310 ],
Don Garretta50bf492017-09-28 18:33:02 -0700311 extra_env={'PATH': mock.ANY},
Don Garrettbf90cdf2017-05-19 15:54:02 -0700312 cwd='/root/repository',
Don Garrettacbb2392017-05-11 18:27:41 -0700313 error_code_ok=True)
Don Garrett7ade05a2017-02-17 13:31:47 -0800314
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600315 # Ensure we write the final build state, as expected.
316 final_state = build_summary.BuildSummary(
317 build_number=314,
318 master_build_id=123456789,
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600319 status=constants.BUILDER_STATUS_PASSED,
320 buildroot_layout=2,
321 branch='branch')
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600322 self.assertEqual(mock_set_last_build_state.mock_calls, [
323 mock.call('/root', final_state)])
324
Benjamin Gordonaee36b82018-02-05 14:25:26 -0700325 # Ensure we clean the chroot, as expected.
326 self.assertEqual(mock_cleanup_chroot.mock_calls, [
327 mock.call('/root/repository')])
328
Don Garrett7ade05a2017-02-17 13:31:47 -0800329
Don Garrettbf90cdf2017-05-19 15:54:02 -0700330class CleanBuildRootTest(cros_test_lib.MockTempDirTestCase):
331 """Tests for CleanBuildRoot method."""
Don Garrett7ade05a2017-02-17 13:31:47 -0800332
333 def setUp(self):
334 """Create standard buildroot contents for cleanup."""
Don Garrettbf90cdf2017-05-19 15:54:02 -0700335 self.root = os.path.join(self.tempdir)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600336 self.previous_build_state = os.path.join(
337 self.root, '.cbuildbot_build_state.json')
Don Garrettbf90cdf2017-05-19 15:54:02 -0700338 self.buildroot = os.path.join(self.root, 'buildroot')
339 self.repo = os.path.join(self.buildroot, '.repo/repo')
Don Garrett36650112018-06-28 15:54:34 -0700340 self.chroot = os.path.join(self.buildroot, 'chroot')
Don Garrettbf90cdf2017-05-19 15:54:02 -0700341 self.general = os.path.join(self.buildroot, 'general/general')
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700342 self.cache = os.path.join(self.buildroot, '.cache')
343 self.distfiles = os.path.join(self.cache, 'distfiles')
Don Garrett7ade05a2017-02-17 13:31:47 -0800344
Don Garrettf324bc32017-05-23 14:00:53 -0700345 self.mock_repo = mock.MagicMock()
Don Garrettbf90cdf2017-05-19 15:54:02 -0700346 self.mock_repo.directory = self.buildroot
Don Garrettf324bc32017-05-23 14:00:53 -0700347
Don Garrettacbb2392017-05-11 18:27:41 -0700348 self.metrics = {}
349
Benjamin Gordon8642bcc2018-05-01 13:49:56 -0600350 def populateBuildroot(self, previous_build_state=None):
Don Garrett7ade05a2017-02-17 13:31:47 -0800351 """Create standard buildroot contents for cleanup."""
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600352 if previous_build_state:
353 osutils.SafeMakedirs(self.root)
354 osutils.WriteFile(self.previous_build_state, previous_build_state)
355
Don Garrett7ade05a2017-02-17 13:31:47 -0800356 # Create files.
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700357 for f in (self.repo, self.chroot, self.general, self.distfiles):
Don Garrette17e1d92017-04-12 15:28:19 -0700358 osutils.Touch(f, makedirs=True)
Don Garrett7ade05a2017-02-17 13:31:47 -0800359
Don Garrette17e1d92017-04-12 15:28:19 -0700360 def testNoBuildroot(self):
Don Garrettbf90cdf2017-05-19 15:54:02 -0700361 """Test CleanBuildRoot with no history."""
Don Garrettf324bc32017-05-23 14:00:53 -0700362 self.mock_repo.branch = 'master'
363
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600364 build_state = build_summary.BuildSummary(
365 status=constants.BUILDER_STATUS_INFLIGHT,
366 buildroot_layout=cbuildbot_launch.BUILDROOT_BUILDROOT_LAYOUT,
367 branch='master')
Don Garrettbf90cdf2017-05-19 15:54:02 -0700368 cbuildbot_launch.CleanBuildRoot(
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600369 self.root, self.mock_repo, self.metrics, build_state)
Don Garrett7ade05a2017-02-17 13:31:47 -0800370
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600371 new_summary = cbuildbot_launch.GetLastBuildState(self.root)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600372 self.assertEqual(new_summary.buildroot_layout, 2)
373 self.assertEqual(new_summary.branch, 'master')
374 self.assertIsNotNone(new_summary.distfiles_ts)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600375 self.assertEqual(new_summary, build_state)
Don Garrett7ade05a2017-02-17 13:31:47 -0800376
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600377 self.assertExists(self.previous_build_state)
378
Don Garrett7ade05a2017-02-17 13:31:47 -0800379 def testBuildrootNoState(self):
Don Garrettbf90cdf2017-05-19 15:54:02 -0700380 """Test CleanBuildRoot with no state information."""
Don Garrett7ade05a2017-02-17 13:31:47 -0800381 self.populateBuildroot()
Don Garrettf324bc32017-05-23 14:00:53 -0700382 self.mock_repo.branch = 'master'
Don Garrett7ade05a2017-02-17 13:31:47 -0800383
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600384 build_state = build_summary.BuildSummary(
385 status=constants.BUILDER_STATUS_INFLIGHT,
386 buildroot_layout=cbuildbot_launch.BUILDROOT_BUILDROOT_LAYOUT,
387 branch='master')
Don Garrettbf90cdf2017-05-19 15:54:02 -0700388 cbuildbot_launch.CleanBuildRoot(
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600389 self.root, self.mock_repo, self.metrics, build_state)
Don Garrett7ade05a2017-02-17 13:31:47 -0800390
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600391 new_summary = cbuildbot_launch.GetLastBuildState(self.root)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600392 self.assertEqual(new_summary.buildroot_layout, 2)
393 self.assertEqual(new_summary.branch, 'master')
394 self.assertIsNotNone(new_summary.distfiles_ts)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600395 self.assertEqual(new_summary, build_state)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700396
Don Garrett60967922017-04-12 18:51:44 -0700397 self.assertNotExists(self.repo)
Don Garrett7ade05a2017-02-17 13:31:47 -0800398 self.assertNotExists(self.chroot)
Don Garrett60967922017-04-12 18:51:44 -0700399 self.assertNotExists(self.general)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700400 self.assertNotExists(self.distfiles)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600401 self.assertExists(self.previous_build_state)
Don Garrett7ade05a2017-02-17 13:31:47 -0800402
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600403 def testBuildrootFormatMismatch(self):
404 """Test CleanBuildRoot with buildroot layout mismatch."""
405 old_build_state = build_summary.BuildSummary(
406 status=constants.BUILDER_STATUS_PASSED,
407 buildroot_layout=1,
408 branch='master')
409 self.populateBuildroot(previous_build_state=old_build_state.to_json())
410 self.mock_repo.branch = 'master'
411
412 build_state = build_summary.BuildSummary(
413 status=constants.BUILDER_STATUS_INFLIGHT,
414 buildroot_layout=cbuildbot_launch.BUILDROOT_BUILDROOT_LAYOUT,
415 branch='master')
416 cbuildbot_launch.CleanBuildRoot(
417 self.root, self.mock_repo, self.metrics, build_state)
418
419 new_summary = cbuildbot_launch.GetLastBuildState(self.root)
420 self.assertEqual(new_summary.buildroot_layout, 2)
421 self.assertEqual(new_summary.branch, 'master')
422 self.assertIsNotNone(new_summary.distfiles_ts)
423 self.assertEqual(new_summary, build_state)
424
425 self.assertNotExists(self.repo)
426 self.assertNotExists(self.chroot)
427 self.assertNotExists(self.general)
428 self.assertNotExists(self.distfiles)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600429 self.assertExists(self.previous_build_state)
430
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600431 def testBuildrootBranchChange(self):
432 """Test CleanBuildRoot with a change in branches."""
433 old_build_state = build_summary.BuildSummary(
434 status=constants.BUILDER_STATUS_PASSED,
435 buildroot_layout=2,
436 branch='branchA')
437 self.populateBuildroot(previous_build_state=old_build_state.to_json())
438 self.mock_repo.branch = 'branchB'
Benjamin Gordon74645232018-05-04 17:40:42 -0600439 m = self.PatchObject(cros_sdk_lib, 'CleanupChrootMount')
Don Garrett7ade05a2017-02-17 13:31:47 -0800440
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600441 build_state = build_summary.BuildSummary(
442 status=constants.BUILDER_STATUS_INFLIGHT,
443 buildroot_layout=cbuildbot_launch.BUILDROOT_BUILDROOT_LAYOUT,
444 branch='branchB')
Don Garrettbf90cdf2017-05-19 15:54:02 -0700445 cbuildbot_launch.CleanBuildRoot(
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600446 self.root, self.mock_repo, self.metrics, build_state)
Don Garrett7ade05a2017-02-17 13:31:47 -0800447
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600448 new_summary = cbuildbot_launch.GetLastBuildState(self.root)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600449 self.assertEqual(new_summary.buildroot_layout, 2)
450 self.assertEqual(new_summary.branch, 'branchB')
451 self.assertIsNotNone(new_summary.distfiles_ts)
452 self.assertEqual(new_summary, build_state)
453
454 self.assertExists(self.repo)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600455 self.assertExists(self.general)
456 self.assertNotExists(self.distfiles)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600457 self.assertExists(self.previous_build_state)
Don Garrett36650112018-06-28 15:54:34 -0700458 m.assert_called_with(self.chroot, delete=True)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600459
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600460 def testBuildrootBranchMatch(self):
461 """Test CleanBuildRoot with no change in branch."""
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 = 'branchA'
468
469 build_state = build_summary.BuildSummary(
470 status=constants.BUILDER_STATUS_INFLIGHT,
471 buildroot_layout=cbuildbot_launch.BUILDROOT_BUILDROOT_LAYOUT,
472 branch='branchA')
473 cbuildbot_launch.CleanBuildRoot(
474 self.root, self.mock_repo, self.metrics, build_state)
475
476 new_summary = cbuildbot_launch.GetLastBuildState(self.root)
477 self.assertEqual(new_summary.buildroot_layout, 2)
478 self.assertEqual(new_summary.branch, 'branchA')
479 self.assertIsNotNone(new_summary.distfiles_ts)
480 self.assertEqual(new_summary, build_state)
481
482 self.assertExists(self.repo)
483 self.assertExists(self.chroot)
484 self.assertExists(self.general)
485 self.assertExists(self.distfiles)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600486 self.assertExists(self.previous_build_state)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700487
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600488 def testBuildrootDistfilesRecentCache(self):
489 """Test CleanBuildRoot does not delete distfiles when cache is recent."""
490 seed_distfiles_ts = time.time() - 60
491 old_build_state = build_summary.BuildSummary(
492 status=constants.BUILDER_STATUS_PASSED,
493 buildroot_layout=2,
494 branch='branchA',
495 distfiles_ts=seed_distfiles_ts)
496 self.populateBuildroot(previous_build_state=old_build_state.to_json())
497 self.mock_repo.branch = 'branchA'
498
499 build_state = build_summary.BuildSummary(
500 status=constants.BUILDER_STATUS_INFLIGHT,
501 buildroot_layout=cbuildbot_launch.BUILDROOT_BUILDROOT_LAYOUT,
502 branch='branchA')
503 cbuildbot_launch.CleanBuildRoot(
504 self.root, self.mock_repo, self.metrics, build_state)
505
506 new_summary = cbuildbot_launch.GetLastBuildState(self.root)
507 self.assertEqual(new_summary.buildroot_layout, 2)
508 self.assertEqual(new_summary.branch, 'branchA')
509 # Same cache creation timestamp is rewritten to state.
510 self.assertEqual(new_summary.distfiles_ts, seed_distfiles_ts)
511 self.assertEqual(new_summary, build_state)
512
513 self.assertExists(self.repo)
514 self.assertExists(self.chroot)
515 self.assertExists(self.general)
516 self.assertExists(self.distfiles)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600517 self.assertExists(self.previous_build_state)
Don Garrette17e1d92017-04-12 15:28:19 -0700518
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600519 def testBuildrootDistfilesCacheExpired(self):
520 """Test CleanBuildRoot when the distfiles cache is too old."""
521 old_build_state = build_summary.BuildSummary(
522 status=constants.BUILDER_STATUS_PASSED,
523 buildroot_layout=2,
524 branch='branchA',
525 distfiles_ts=100.0)
526 self.populateBuildroot(previous_build_state=old_build_state.to_json())
527 self.mock_repo.branch = 'branchA'
528
529 build_state = build_summary.BuildSummary(
530 status=constants.BUILDER_STATUS_INFLIGHT,
531 buildroot_layout=cbuildbot_launch.BUILDROOT_BUILDROOT_LAYOUT,
532 branch='branchA')
533 cbuildbot_launch.CleanBuildRoot(
534 self.root, self.mock_repo, self.metrics, build_state)
535
536 new_summary = cbuildbot_launch.GetLastBuildState(self.root)
537 self.assertEqual(new_summary.buildroot_layout, 2)
538 self.assertEqual(new_summary.branch, 'branchA')
539 self.assertIsNotNone(new_summary.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.assertNotExists(self.distfiles)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600546 self.assertExists(self.previous_build_state)
547
548 def testBuildrootRepoCleanFailure(self):
549 """Test CleanBuildRoot with repo checkout failure."""
550 old_build_state = build_summary.BuildSummary(
551 status=constants.BUILDER_STATUS_PASSED,
552 buildroot_layout=1,
553 branch='branchA')
554 self.populateBuildroot(previous_build_state=old_build_state.to_json())
555 self.mock_repo.branch = 'branchA'
556 self.mock_repo.BuildRootGitCleanup.side_effect = Exception
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.assertNotExists(self.repo)
572 self.assertNotExists(self.chroot)
573 self.assertNotExists(self.general)
574 self.assertNotExists(self.distfiles)
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600575 self.assertExists(self.previous_build_state)
Don Garrettf324bc32017-05-23 14:00:53 -0700576
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600577 def testGetCurrentBuildStateNoArgs(self):
578 """Tests GetCurrentBuildState without arguments."""
579 options = cbuildbot_launch.PreParseArguments([
580 '--buildroot', self.root, 'config'
581 ])
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600582 state = cbuildbot_launch.GetCurrentBuildState(options, 'master')
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600583
584 expected_state = build_summary.BuildSummary(
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600585 status=constants.BUILDER_STATUS_INFLIGHT,
586 buildroot_layout=2,
587 branch='master')
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600588 self.assertEqual(state, expected_state)
589
590 def testGetCurrentBuildStateHasArgs(self):
591 """Tests GetCurrentBuildState with arguments."""
592 options = cbuildbot_launch.PreParseArguments([
593 '--buildroot', self.root,
594 '--buildnumber', '20',
595 '--master-build-id', '50',
596 'config'
597 ])
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600598 state = cbuildbot_launch.GetCurrentBuildState(options, 'branchA')
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600599
600 expected_state = build_summary.BuildSummary(
601 build_number=20,
602 master_build_id=50,
Benjamin Gordon8b6d4122018-04-26 13:38:39 -0600603 status=constants.BUILDER_STATUS_INFLIGHT,
604 buildroot_layout=2,
605 branch='branchA')
606 self.assertEqual(state, expected_state)
607
608 def testGetCurrentBuildStateLayout(self):
609 """Test that GetCurrentBuildState uses the current buildroot layout."""
610 # Change to a future version.
611 self.PatchObject(cbuildbot_launch, 'BUILDROOT_BUILDROOT_LAYOUT', 22)
612
613 options = cbuildbot_launch.PreParseArguments([
614 '--buildroot', self.root, 'config'
615 ])
616 state = cbuildbot_launch.GetCurrentBuildState(options, 'branchA')
617
618 expected_state = build_summary.BuildSummary(
619 status=constants.BUILDER_STATUS_INFLIGHT,
620 buildroot_layout=22,
621 branch='branchA')
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600622 self.assertEqual(state, expected_state)
623
624 def testGetLastBuildStateNoFile(self):
625 """Tests GetLastBuildState if the file is missing."""
626 osutils.SafeMakedirs(self.root)
627 state = cbuildbot_launch.GetLastBuildState(self.root)
628 self.assertEqual(state, build_summary.BuildSummary())
629
630 def testGetLastBuildStateBadFile(self):
631 """Tests GetLastBuildState if the file contains invalid JSON."""
632 osutils.SafeMakedirs(self.root)
633 osutils.WriteFile(self.previous_build_state, '}}')
634 state = cbuildbot_launch.GetLastBuildState(self.root)
635 self.assertEqual(state, build_summary.BuildSummary())
636
637 def testGetLastBuildStateMissingBuildStatus(self):
638 """Tests GetLastBuildState if the file doesn't have a valid status."""
639 osutils.SafeMakedirs(self.root)
640 osutils.WriteFile(self.previous_build_state, '{"build_number": "3"}')
641 state = cbuildbot_launch.GetLastBuildState(self.root)
642 self.assertEqual(state, build_summary.BuildSummary())
643
644 def testGetLastBuildStateGoodFile(self):
645 """Tests GetLastBuildState on a good file."""
646 osutils.SafeMakedirs(self.root)
647 osutils.WriteFile(
648 self.previous_build_state,
649 '{"build_number": 1, "master_build_id": 3, "status": "pass"}')
650 state = cbuildbot_launch.GetLastBuildState(self.root)
651 self.assertEqual(
652 state,
653 build_summary.BuildSummary(
654 build_number=1, master_build_id=3, status='pass'))
655
656 def testSetLastBuildState(self):
657 """Verifies that SetLastBuildState writes to the expected file."""
658 osutils.SafeMakedirs(self.root)
659 old_state = build_summary.BuildSummary(
660 build_number=314,
661 master_build_id=2178,
662 status=constants.BUILDER_STATUS_PASSED)
663 cbuildbot_launch.SetLastBuildState(self.root, old_state)
664
665 saved_state = osutils.ReadFile(self.previous_build_state)
666 new_state = build_summary.BuildSummary()
667 new_state.from_json(saved_state)
668
669 self.assertEqual(old_state, new_state)