blob: c2f8bd970119d7376a396f90d08a3cc02f51b45c [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 Garrettc4114cc2016-11-01 20:04:06 -070018from chromite.lib import cros_build_lib_unittest
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
Don Garrett066e6f52017-09-28 19:14:01 -070093class RunDepotToolsEnsureBootstrap(cros_build_lib_unittest.RunCommandTestCase,
94 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
Don Garrett597ddff2017-02-17 18:29:37 -0800112class RunTests(cros_build_lib_unittest.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(
177 build_number=0, master_build_id=0, status=mock.ANY)
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 Gordon90b2dd92018-04-12 14:04:21 -0600232 mock_summary = build_summary.BuildSummary()
233 mock_summary.build_number = 313
234 mock_summary.master_build_id = 123123123
235 mock_summary.status = constants.BUILDER_STATUS_FAILED
236
237 mock_get_last_build_state = self.PatchObject(
238 cbuildbot_launch, 'GetLastBuildState', autospec=True,
239 return_value=mock_summary)
Don Garrettf324bc32017-05-23 14:00:53 -0700240 mock_repo_create = self.PatchObject(repository, 'RepoRepository',
241 autospec=True, return_value=mock_repo)
Don Garrettbf90cdf2017-05-19 15:54:02 -0700242 mock_clean = self.PatchObject(cbuildbot_launch, 'CleanBuildRoot',
Don Garrett0c54ed72017-03-03 11:18:57 -0800243 autospec=True)
244 mock_checkout = self.PatchObject(cbuildbot_launch, 'InitialCheckout',
Don Garrett86881cb2017-02-15 15:41:55 -0800245 autospec=True)
Benjamin Gordonaee36b82018-02-05 14:25:26 -0700246 mock_cleanup_chroot = self.PatchObject(cbuildbot_launch, 'CleanupChroot',
247 autospec=True)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600248 mock_set_last_build_state = self.PatchObject(
249 cbuildbot_launch, 'SetLastBuildState', autospec=True)
Don Garrettc4114cc2016-11-01 20:04:06 -0700250
Don Garrettbf90cdf2017-05-19 15:54:02 -0700251 cbuildbot_launch._main(['--buildroot', '/root',
Don Garrettacbb2392017-05-11 18:27:41 -0700252 '--branch', 'branch',
253 '--git-cache-dir', '/git-cache',
Don Garrettd1d90dd2017-06-13 17:35:52 -0700254 '--remote-trybot',
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600255 '--master-build-id', '123456789',
256 '--buildnumber', '314',
Don Garrettacbb2392017-05-11 18:27:41 -0700257 'config'])
Don Garrettc4114cc2016-11-01 20:04:06 -0700258
Don Garrettf324bc32017-05-23 14:00:53 -0700259 # Did we create the repo instance correctly?
260 self.assertEqual(mock_repo_create.mock_calls,
Don Garrettbf90cdf2017-05-19 15:54:02 -0700261 [mock.call(EXPECTED_MANIFEST_URL, '/root/repository',
Don Garrettf324bc32017-05-23 14:00:53 -0700262 git_cache_dir='/git-cache', branch='branch')])
263
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600264 # Ensure we look up the previous status.
265 self.assertEqual(mock_get_last_build_state.mock_calls, [
266 mock.call('/root')])
267
Don Garrett7ade05a2017-02-17 13:31:47 -0800268 # Ensure we clean, as expected.
Don Garrettbf90cdf2017-05-19 15:54:02 -0700269 self.assertEqual(mock_clean.mock_calls, [
Don Garrettd1d90dd2017-06-13 17:35:52 -0700270 mock.call('/root',
271 mock_repo,
272 {
273 'branch_name': 'branch',
274 'tryjob': True,
275 'build_config': 'config',
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600276 },
277 build_summary.BuildSummary(
278 build_number=314,
279 master_build_id=123456789,
280 status=mock.ANY
281 ))])
Don Garrett7ade05a2017-02-17 13:31:47 -0800282
Don Garrett86881cb2017-02-15 15:41:55 -0800283 # Ensure we checkout, as expected.
284 self.assertEqual(mock_checkout.mock_calls,
Don Garrettf324bc32017-05-23 14:00:53 -0700285 [mock.call(mock_repo)])
Don Garrett86881cb2017-02-15 15:41:55 -0800286
287 # Ensure we invoke cbuildbot, as expected.
288 self.assertCommandCalled(
Don Garrett5cd946b2017-07-20 13:42:20 -0700289 [
290 '/root/repository/chromite/bin/cbuildbot',
291 'config',
292 '--buildroot', '/root/repository',
293 '--branch', 'branch',
294 '--git-cache-dir', '/git-cache',
295 '--remote-trybot',
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600296 '--master-build-id', '123456789',
297 '--buildnumber', '314',
298 '--previous-build-state',
299 'eyJzdGF0dXMiOiAiZmFpbCIsICJtYXN0ZXJfYnVpbGRfaWQiOiAxM'
300 'jMxMjMxMjMsICJidWlsZF9udW1iZXIiOiAzMTN9',
Don Garrett5cd946b2017-07-20 13:42:20 -0700301 '--ts-mon-task-num', '1',
302 ],
Don Garretta50bf492017-09-28 18:33:02 -0700303 extra_env={'PATH': mock.ANY},
Don Garrettbf90cdf2017-05-19 15:54:02 -0700304 cwd='/root/repository',
Don Garrettacbb2392017-05-11 18:27:41 -0700305 error_code_ok=True)
Don Garrett7ade05a2017-02-17 13:31:47 -0800306
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600307 # Ensure we write the final build state, as expected.
308 final_state = build_summary.BuildSummary(
309 build_number=314,
310 master_build_id=123456789,
311 status=constants.BUILDER_STATUS_PASSED)
312 self.assertEqual(mock_set_last_build_state.mock_calls, [
313 mock.call('/root', final_state)])
314
Benjamin Gordonaee36b82018-02-05 14:25:26 -0700315 # Ensure we clean the chroot, as expected.
316 self.assertEqual(mock_cleanup_chroot.mock_calls, [
317 mock.call('/root/repository')])
318
Don Garrett7ade05a2017-02-17 13:31:47 -0800319
Don Garrettbf90cdf2017-05-19 15:54:02 -0700320class CleanBuildRootTest(cros_test_lib.MockTempDirTestCase):
321 """Tests for CleanBuildRoot method."""
Don Garrett7ade05a2017-02-17 13:31:47 -0800322
323 def setUp(self):
324 """Create standard buildroot contents for cleanup."""
Don Garrettbf90cdf2017-05-19 15:54:02 -0700325 self.root = os.path.join(self.tempdir)
Don Garrette17e1d92017-04-12 15:28:19 -0700326 self.state = os.path.join(self.root, '.cbuildbot_launch_state')
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600327 self.previous_build_state = os.path.join(
328 self.root, '.cbuildbot_build_state.json')
Don Garrettbf90cdf2017-05-19 15:54:02 -0700329 self.buildroot = os.path.join(self.root, 'buildroot')
330 self.repo = os.path.join(self.buildroot, '.repo/repo')
331 self.chroot = os.path.join(self.buildroot, 'chroot/chroot')
332 self.general = os.path.join(self.buildroot, 'general/general')
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700333 self.cache = os.path.join(self.buildroot, '.cache')
334 self.distfiles = os.path.join(self.cache, 'distfiles')
Don Garrett7ade05a2017-02-17 13:31:47 -0800335
Don Garrettf324bc32017-05-23 14:00:53 -0700336 self.mock_repo = mock.MagicMock()
Don Garrettbf90cdf2017-05-19 15:54:02 -0700337 self.mock_repo.directory = self.buildroot
Don Garrettf324bc32017-05-23 14:00:53 -0700338
Don Garrettacbb2392017-05-11 18:27:41 -0700339 self.metrics = {}
340
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600341 def populateBuildroot(self, state=None, previous_build_state=None):
Don Garrett7ade05a2017-02-17 13:31:47 -0800342 """Create standard buildroot contents for cleanup."""
343 if state:
Don Garrettbf90cdf2017-05-19 15:54:02 -0700344 osutils.SafeMakedirs(self.root)
Don Garrett7ade05a2017-02-17 13:31:47 -0800345 osutils.WriteFile(self.state, state)
346
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600347 if previous_build_state:
348 osutils.SafeMakedirs(self.root)
349 osutils.WriteFile(self.previous_build_state, previous_build_state)
350
Don Garrett7ade05a2017-02-17 13:31:47 -0800351 # Create files.
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700352 for f in (self.repo, self.chroot, self.general, self.distfiles):
Don Garrette17e1d92017-04-12 15:28:19 -0700353 osutils.Touch(f, makedirs=True)
Don Garrett7ade05a2017-02-17 13:31:47 -0800354
Don Garrette17e1d92017-04-12 15:28:19 -0700355 def testNoBuildroot(self):
Don Garrettbf90cdf2017-05-19 15:54:02 -0700356 """Test CleanBuildRoot with no history."""
Don Garrettf324bc32017-05-23 14:00:53 -0700357 self.mock_repo.branch = 'master'
358
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600359 build_state = build_summary.BuildSummary()
Don Garrettbf90cdf2017-05-19 15:54:02 -0700360 cbuildbot_launch.CleanBuildRoot(
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600361 self.root, self.mock_repo, self.metrics, build_state)
Don Garrett7ade05a2017-02-17 13:31:47 -0800362
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700363 version, branch, distfiles_ts = cbuildbot_launch.GetState(self.root)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600364 new_summary = cbuildbot_launch.GetLastBuildState(self.root)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700365 self.assertEqual(version, 2)
366 self.assertEqual(branch, 'master')
367 self.assertIsNotNone(distfiles_ts)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600368 self.assertEqual(new_summary, build_state)
Don Garrett7ade05a2017-02-17 13:31:47 -0800369
370 def testBuildrootNoState(self):
Don Garrettbf90cdf2017-05-19 15:54:02 -0700371 """Test CleanBuildRoot with no state information."""
Don Garrett7ade05a2017-02-17 13:31:47 -0800372 self.populateBuildroot()
Don Garrettf324bc32017-05-23 14:00:53 -0700373 self.mock_repo.branch = 'master'
Don Garrett7ade05a2017-02-17 13:31:47 -0800374
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600375 build_state = build_summary.BuildSummary()
Don Garrettbf90cdf2017-05-19 15:54:02 -0700376 cbuildbot_launch.CleanBuildRoot(
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600377 self.root, self.mock_repo, self.metrics, build_state)
Don Garrett7ade05a2017-02-17 13:31:47 -0800378
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700379 version, branch, distfiles_ts = cbuildbot_launch.GetState(self.root)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600380 new_summary = cbuildbot_launch.GetLastBuildState(self.root)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700381 self.assertEqual(version, 2)
382 self.assertEqual(branch, 'master')
383 self.assertIsNotNone(distfiles_ts)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600384 self.assertEqual(new_summary, build_state)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700385
Don Garrett60967922017-04-12 18:51:44 -0700386 self.assertNotExists(self.repo)
Don Garrett7ade05a2017-02-17 13:31:47 -0800387 self.assertNotExists(self.chroot)
Don Garrett60967922017-04-12 18:51:44 -0700388 self.assertNotExists(self.general)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700389 self.assertNotExists(self.distfiles)
Don Garrett60967922017-04-12 18:51:44 -0700390
391 def testBuildrootFormatMismatch(self):
Don Garrettbf90cdf2017-05-19 15:54:02 -0700392 """Test CleanBuildRoot with no state information."""
Don Garrett125d4dc2017-04-25 16:26:03 -0700393 self.populateBuildroot('0 master')
Don Garrettf324bc32017-05-23 14:00:53 -0700394 self.mock_repo.branch = 'master'
Don Garrett60967922017-04-12 18:51:44 -0700395
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600396 build_state = build_summary.BuildSummary()
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 Garrett60967922017-04-12 18:51:44 -0700399
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700400 version, branch, distfiles_ts = cbuildbot_launch.GetState(self.root)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600401 new_summary = cbuildbot_launch.GetLastBuildState(self.root)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700402 self.assertEqual(version, 2)
403 self.assertEqual(branch, 'master')
404 self.assertIsNotNone(distfiles_ts)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600405 self.assertEqual(new_summary, build_state)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700406
Don Garrett60967922017-04-12 18:51:44 -0700407 self.assertNotExists(self.repo)
408 self.assertNotExists(self.chroot)
409 self.assertNotExists(self.general)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700410 self.assertNotExists(self.distfiles)
Don Garrett7ade05a2017-02-17 13:31:47 -0800411
412 def testBuildrootBranchChange(self):
Don Garrettbf90cdf2017-05-19 15:54:02 -0700413 """Test CleanBuildRoot with a change in branches."""
414 self.populateBuildroot('2 branchA')
Don Garrettf324bc32017-05-23 14:00:53 -0700415 self.mock_repo.branch = 'branchB'
Benjamin Gordon59ba2f82017-08-28 15:31:06 -0600416 m = self.PatchObject(cros_build_lib, 'CleanupChrootMount')
Don Garrett7ade05a2017-02-17 13:31:47 -0800417
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600418 build_state = build_summary.BuildSummary()
Don Garrettbf90cdf2017-05-19 15:54:02 -0700419 cbuildbot_launch.CleanBuildRoot(
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600420 self.root, self.mock_repo, self.metrics, build_state)
Don Garrett7ade05a2017-02-17 13:31:47 -0800421
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700422 version, branch, distfiles_ts = cbuildbot_launch.GetState(self.root)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600423 new_summary = cbuildbot_launch.GetLastBuildState(self.root)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700424 self.assertEqual(version, 2)
425 self.assertEqual(branch, 'branchB')
426 self.assertIsNotNone(distfiles_ts)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600427 self.assertEqual(new_summary, build_state)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700428
Don Garrett7ade05a2017-02-17 13:31:47 -0800429 self.assertExists(self.repo)
430 self.assertNotExists(self.chroot)
431 self.assertExists(self.general)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700432 self.assertNotExists(self.distfiles)
Benjamin Gordon59ba2f82017-08-28 15:31:06 -0600433 m.assert_called()
Don Garrett7ade05a2017-02-17 13:31:47 -0800434
435 def testBuildrootBranchMatch(self):
Don Garrettbf90cdf2017-05-19 15:54:02 -0700436 """Test CleanBuildRoot with no change in branch."""
437 self.populateBuildroot('2 branchA')
Don Garrettf324bc32017-05-23 14:00:53 -0700438 self.mock_repo.branch = 'branchA'
Don Garrett7ade05a2017-02-17 13:31:47 -0800439
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600440 build_state = build_summary.BuildSummary()
Don Garrettbf90cdf2017-05-19 15:54:02 -0700441 cbuildbot_launch.CleanBuildRoot(
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600442 self.root, self.mock_repo, self.metrics, build_state)
Don Garrett7ade05a2017-02-17 13:31:47 -0800443
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700444 version, branch, distfiles_ts = cbuildbot_launch.GetState(self.root)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600445 new_summary = cbuildbot_launch.GetLastBuildState(self.root)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700446 self.assertEqual(version, 2)
447 self.assertEqual(branch, 'branchA')
448 self.assertIsNotNone(distfiles_ts)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600449 self.assertEqual(new_summary, build_state)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700450
Don Garrett7ade05a2017-02-17 13:31:47 -0800451 self.assertExists(self.repo)
452 self.assertExists(self.chroot)
453 self.assertExists(self.general)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700454 self.assertExists(self.distfiles)
455
456 def testBuildrootDistfilesRecentCache(self):
457 """Test CleanBuildRoot does not delete distfiles when cache is recent."""
458 seed_distfiles_ts = time.time() - 60
459 self.populateBuildroot('2 branchA %f' % seed_distfiles_ts)
460 self.mock_repo.branch = 'branchA'
461
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600462 build_state = build_summary.BuildSummary()
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700463 cbuildbot_launch.CleanBuildRoot(
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600464 self.root, self.mock_repo, self.metrics, build_state)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700465
466 version, branch, distfiles_ts = cbuildbot_launch.GetState(self.root)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600467 new_summary = cbuildbot_launch.GetLastBuildState(self.root)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700468 self.assertEqual(version, 2)
469 self.assertEqual(branch, 'branchA')
470 # Same cache creation timestamp is rewritten to state.
471 self.assertEqual(distfiles_ts, seed_distfiles_ts)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600472 self.assertEqual(new_summary, build_state)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700473
474 self.assertExists(self.repo)
475 self.assertExists(self.chroot)
476 self.assertExists(self.general)
477 self.assertExists(self.distfiles)
478
479 def testBuildrootDistfilesCacheExpired(self):
480 """Test CleanBuildRoot when the distfiles cache is too old."""
481 self.populateBuildroot('2 branchA 100.000000')
482 self.mock_repo.branch = 'branchA'
483
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600484 build_state = build_summary.BuildSummary()
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700485 cbuildbot_launch.CleanBuildRoot(
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600486 self.root, self.mock_repo, self.metrics, build_state)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700487
488 version, branch, distfiles_ts = cbuildbot_launch.GetState(self.root)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600489 new_summary = cbuildbot_launch.GetLastBuildState(self.root)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700490 self.assertEqual(version, 2)
491 self.assertEqual(branch, 'branchA')
492 self.assertIsNotNone(distfiles_ts)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600493 self.assertEqual(new_summary, build_state)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700494
495 self.assertExists(self.repo)
496 self.assertExists(self.chroot)
497 self.assertExists(self.general)
498 self.assertNotExists(self.distfiles)
Don Garrette17e1d92017-04-12 15:28:19 -0700499
Don Garrettf324bc32017-05-23 14:00:53 -0700500 def testBuildrootRepoCleanFailure(self):
Don Garrettbf90cdf2017-05-19 15:54:02 -0700501 """Test CleanBuildRoot with repo checkout failure."""
Don Garrettf324bc32017-05-23 14:00:53 -0700502 self.populateBuildroot('1 branchA')
503 self.mock_repo.branch = 'branchA'
504 self.mock_repo.BuildRootGitCleanup.side_effect = Exception
505
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600506 build_state = build_summary.BuildSummary()
Don Garrettbf90cdf2017-05-19 15:54:02 -0700507 cbuildbot_launch.CleanBuildRoot(
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600508 self.root, self.mock_repo, self.metrics, build_state)
Don Garrettf324bc32017-05-23 14:00:53 -0700509
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700510 version, branch, distfiles_ts = cbuildbot_launch.GetState(self.root)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600511 new_summary = cbuildbot_launch.GetLastBuildState(self.root)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700512 self.assertEqual(version, 2)
513 self.assertEqual(branch, 'branchA')
514 self.assertIsNotNone(distfiles_ts)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600515 self.assertEqual(new_summary, build_state)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700516
Don Garrettf324bc32017-05-23 14:00:53 -0700517 self.assertNotExists(self.repo)
518 self.assertNotExists(self.chroot)
519 self.assertNotExists(self.general)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700520 self.assertNotExists(self.distfiles)
Don Garrettf324bc32017-05-23 14:00:53 -0700521
Don Garrettbf90cdf2017-05-19 15:54:02 -0700522 def testGetState(self):
523 """Test GetState."""
Don Garrett60967922017-04-12 18:51:44 -0700524 # No root dir.
Don Garrettbf90cdf2017-05-19 15:54:02 -0700525 results = cbuildbot_launch.GetState(self.root)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700526 self.assertEqual(results, (0, '', None))
Don Garrett60967922017-04-12 18:51:44 -0700527
528 # Empty root dir.
529 osutils.SafeMakedirs(self.root)
Don Garrettbf90cdf2017-05-19 15:54:02 -0700530 results = cbuildbot_launch.GetState(self.root)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700531 self.assertEqual(results, (0, '', None))
Don Garrett60967922017-04-12 18:51:44 -0700532
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700533 # Empty contents
Don Garrett60967922017-04-12 18:51:44 -0700534 osutils.WriteFile(self.state, '')
Don Garrettbf90cdf2017-05-19 15:54:02 -0700535 results = cbuildbot_launch.GetState(self.root)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700536 self.assertEqual(results, (0, '', None))
Don Garrett60967922017-04-12 18:51:44 -0700537
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700538 # Old format contents
Don Garrett60967922017-04-12 18:51:44 -0700539 osutils.WriteFile(self.state, 'happy-branch')
Don Garrettbf90cdf2017-05-19 15:54:02 -0700540 results = cbuildbot_launch.GetState(self.root)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700541 self.assertEqual(results, (0, '', None))
Don Garrett60967922017-04-12 18:51:44 -0700542
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700543 # Expected contents, without distfiles timestamp
Don Garrett60967922017-04-12 18:51:44 -0700544 osutils.WriteFile(self.state, '1 happy-branch')
Don Garrettbf90cdf2017-05-19 15:54:02 -0700545 results = cbuildbot_launch.GetState(self.root)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700546 self.assertEqual(results, (1, 'happy-branch', None))
Don Garrett60967922017-04-12 18:51:44 -0700547
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700548 # Expected contents
549 osutils.WriteFile(self.state, '1 happy-branch 1000.33')
550 version, branch, distfiles_ts = cbuildbot_launch.GetState(self.root)
551 self.assertEqual(version, 1)
552 self.assertEqual(branch, 'happy-branch')
553 self.assertEqual(distfiles_ts, 1000.33)
Don Garrett60967922017-04-12 18:51:44 -0700554
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700555 # Future layout version contents
556 osutils.WriteFile(self.state, '22 happy-branch 222')
557 version, branch, distfiles_ts = cbuildbot_launch.GetState(self.root)
558 self.assertEqual(version, 22)
559 self.assertEqual(branch, 'happy-branch')
560 self.assertEqual(distfiles_ts, 222)
561
562 # Read write
Don Garrettbf90cdf2017-05-19 15:54:02 -0700563 cbuildbot_launch.SetState('happy-branch', self.root)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700564 version, branch, distfiles_ts = cbuildbot_launch.GetState(self.root)
565 self.assertEqual(version, 2)
566 self.assertEqual(branch, 'happy-branch')
567 self.assertIsNotNone(distfiles_ts)
Don Garrett60967922017-04-12 18:51:44 -0700568
Don Garrettbf90cdf2017-05-19 15:54:02 -0700569 def testSetState(self):
570 """Test SetState."""
Don Garrett60967922017-04-12 18:51:44 -0700571 # Write out a state file.
572 osutils.SafeMakedirs(self.root)
Don Garrettbf90cdf2017-05-19 15:54:02 -0700573 cbuildbot_launch.SetState('happy-branch', self.root)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700574 state_file_parts = osutils.ReadFile(self.state).split()
575 self.assertEqual(state_file_parts[:2], ['2', 'happy-branch'])
576 # Will flake if this test takes > 1 hour to run.
577 self.assertGreater(float(state_file_parts[2]), time.time() - 3600)
578
579 # Explicitly provide a timestamp
580 cbuildbot_launch.SetState('happy-branch', self.root,
581 333.33)
582 state_file_parts = osutils.ReadFile(self.state).split()
583 self.assertEqual(state_file_parts,
584 ['2', 'happy-branch', '333.330000'])
Don Garrett60967922017-04-12 18:51:44 -0700585
586 # Change to a future version.
587 self.PatchObject(cbuildbot_launch, 'BUILDROOT_BUILDROOT_LAYOUT', 22)
Don Garrettbf90cdf2017-05-19 15:54:02 -0700588 cbuildbot_launch.SetState('happy-branch', self.root)
Prathmesh Prabhuc41a0f52018-04-03 13:26:52 -0700589 state_file_parts = osutils.ReadFile(self.state).split()
590 self.assertEqual(state_file_parts[:2], ['22', 'happy-branch'])
591 # Will flake if this test takes > 1 hour to run.
592 self.assertGreater(float(state_file_parts[2]), time.time() - 3600)
Benjamin Gordon90b2dd92018-04-12 14:04:21 -0600593
594 def testGetCurrentBuildStateNoArgs(self):
595 """Tests GetCurrentBuildState without arguments."""
596 options = cbuildbot_launch.PreParseArguments([
597 '--buildroot', self.root, 'config'
598 ])
599 state = cbuildbot_launch.GetCurrentBuildState(options)
600
601 expected_state = build_summary.BuildSummary(
602 status=constants.BUILDER_STATUS_INFLIGHT)
603 self.assertEqual(state, expected_state)
604
605 def testGetCurrentBuildStateHasArgs(self):
606 """Tests GetCurrentBuildState with arguments."""
607 options = cbuildbot_launch.PreParseArguments([
608 '--buildroot', self.root,
609 '--buildnumber', '20',
610 '--master-build-id', '50',
611 'config'
612 ])
613 state = cbuildbot_launch.GetCurrentBuildState(options)
614
615 expected_state = build_summary.BuildSummary(
616 build_number=20,
617 master_build_id=50,
618 status=constants.BUILDER_STATUS_INFLIGHT)
619 self.assertEqual(state, expected_state)
620
621 def testGetLastBuildStateNoFile(self):
622 """Tests GetLastBuildState if the file is missing."""
623 osutils.SafeMakedirs(self.root)
624 state = cbuildbot_launch.GetLastBuildState(self.root)
625 self.assertEqual(state, build_summary.BuildSummary())
626
627 def testGetLastBuildStateBadFile(self):
628 """Tests GetLastBuildState if the file contains invalid JSON."""
629 osutils.SafeMakedirs(self.root)
630 osutils.WriteFile(self.previous_build_state, '}}')
631 state = cbuildbot_launch.GetLastBuildState(self.root)
632 self.assertEqual(state, build_summary.BuildSummary())
633
634 def testGetLastBuildStateMissingBuildStatus(self):
635 """Tests GetLastBuildState if the file doesn't have a valid status."""
636 osutils.SafeMakedirs(self.root)
637 osutils.WriteFile(self.previous_build_state, '{"build_number": "3"}')
638 state = cbuildbot_launch.GetLastBuildState(self.root)
639 self.assertEqual(state, build_summary.BuildSummary())
640
641 def testGetLastBuildStateGoodFile(self):
642 """Tests GetLastBuildState on a good file."""
643 osutils.SafeMakedirs(self.root)
644 osutils.WriteFile(
645 self.previous_build_state,
646 '{"build_number": 1, "master_build_id": 3, "status": "pass"}')
647 state = cbuildbot_launch.GetLastBuildState(self.root)
648 self.assertEqual(
649 state,
650 build_summary.BuildSummary(
651 build_number=1, master_build_id=3, status='pass'))
652
653 def testSetLastBuildState(self):
654 """Verifies that SetLastBuildState writes to the expected file."""
655 osutils.SafeMakedirs(self.root)
656 old_state = build_summary.BuildSummary(
657 build_number=314,
658 master_build_id=2178,
659 status=constants.BUILDER_STATUS_PASSED)
660 cbuildbot_launch.SetLastBuildState(self.root, old_state)
661
662 saved_state = osutils.ReadFile(self.previous_build_state)
663 new_state = build_summary.BuildSummary()
664 new_state.from_json(saved_state)
665
666 self.assertEqual(old_state, new_state)