blob: c221fb5ae5ddf52c522489abb1244f3af32addac [file] [log] [blame]
David Jamesbb20ac82012-07-18 10:59:16 -07001# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
David James8c846492011-01-25 17:07:29 -08002# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
Mike Frysingerc6824f62014-02-03 11:09:44 -05005"""Unittests for upload_prebuilts.py."""
6
David James8c846492011-01-25 17:07:29 -08007import copy
David James8fa34ea2011-04-15 13:00:20 -07008import multiprocessing
Mike Frysinger40ffb532021-02-12 07:36:08 -05009import os
David James8c846492011-01-25 17:07:29 -080010import tempfile
Mike Frysinger166fea02021-02-12 05:30:33 -050011from unittest import mock
Chris Sosa471532a2011-02-01 15:10:06 -080012
Mike Frysinger40ffb532021-02-12 07:36:08 -050013from chromite.lib import binpkg
Brian Harringc92788f2012-09-21 18:07:15 -070014from chromite.lib import cros_test_lib
David James2c7ccb42012-11-04 15:34:28 -080015from chromite.lib import gs
Zdenek Behanc0e18762012-09-22 04:06:17 +020016from chromite.lib import osutils
Mike Frysinger36870f92015-04-12 02:59:55 -040017from chromite.lib import parallel_unittest
Prathmesh Prabhu421eef22014-10-16 17:13:19 -070018from chromite.lib import portage_util
Mike Frysinger40ffb532021-02-12 07:36:08 -050019from chromite.scripts import upload_prebuilts as prebuilt
David James8c846492011-01-25 17:07:29 -080020
Mike Frysinger68182472014-11-05 22:38:39 -050021
Mike Frysinger27e21b72018-07-12 14:20:21 -040022# pylint: disable=protected-access
23
24
David James615e5b52011-06-03 11:10:15 -070025PUBLIC_PACKAGES = [{'CPV': 'gtk+/public1', 'SHA1': '1', 'MTIME': '1'},
David James8c846492011-01-25 17:07:29 -080026 {'CPV': 'gtk+/public2', 'SHA1': '2',
David James615e5b52011-06-03 11:10:15 -070027 'PATH': 'gtk+/foo.tgz', 'MTIME': '2'}]
28PRIVATE_PACKAGES = [{'CPV': 'private', 'SHA1': '3', 'MTIME': '3'}]
David James8c846492011-01-25 17:07:29 -080029
30
31def SimplePackageIndex(header=True, packages=True):
Chris Sosa58669192011-06-30 12:45:03 -070032 pkgindex = binpkg.PackageIndex()
33 if header:
David James2c7ccb42012-11-04 15:34:28 -080034 pkgindex.header['URI'] = 'gs://example'
Chris Sosa58669192011-06-30 12:45:03 -070035 if packages:
36 pkgindex.packages = copy.deepcopy(PUBLIC_PACKAGES + PRIVATE_PACKAGES)
37 return pkgindex
David James8c846492011-01-25 17:07:29 -080038
39
Brian Harringc92788f2012-09-21 18:07:15 -070040class TestUpdateFile(cros_test_lib.TempDirTestCase):
Mike Frysingerc6824f62014-02-03 11:09:44 -050041 """Tests for the UpdateLocalFile function."""
David James8c846492011-01-25 17:07:29 -080042
43 def setUp(self):
Mike Frysingerd6e2df02014-11-26 02:55:04 -050044 self.contents_str = [
45 '# comment that should be skipped',
46 'PKGDIR="/var/lib/portage/pkgs"',
47 'PORTAGE_BINHOST="http://no.thanks.com"',
48 'portage portage-20100310.tar.bz2',
49 'COMPILE_FLAGS="some_value=some_other"',
50 ]
Zdenek Behanc0e18762012-09-22 04:06:17 +020051 self.version_file = os.path.join(self.tempdir, 'version')
52 osutils.WriteFile(self.version_file, '\n'.join(self.contents_str))
David James8c846492011-01-25 17:07:29 -080053
David James8c846492011-01-25 17:07:29 -080054 def _read_version_file(self, version_file=None):
55 """Read the contents of self.version_file and return as a list."""
56 if not version_file:
57 version_file = self.version_file
58
Sergey Frolov89d28242022-06-06 17:49:20 -060059 with open(version_file) as version_fh:
David James8c846492011-01-25 17:07:29 -080060 return [line.strip() for line in version_fh.readlines()]
Sergey Frolov89d28242022-06-06 17:49:20 -060061
David James8c846492011-01-25 17:07:29 -080062
63 def _verify_key_pair(self, key, val):
64 file_contents = self._read_version_file()
Sergey Frolov09280f12022-06-06 17:47:32 -060065
66 # Make sure 'key' entry is only found once.
67 entry_found = False
68
69 # Ensure value is wrapped on quotes.
David James8c846492011-01-25 17:07:29 -080070 if '"' not in val:
71 val = '"%s"' % val
Sergey Frolov09280f12022-06-06 17:47:32 -060072
73 # Inspect file contents.
David James8c846492011-01-25 17:07:29 -080074 for entry in file_contents:
75 if '=' not in entry:
76 continue
Sergey Frolov09280f12022-06-06 17:47:32 -060077 file_key, file_val = entry.split('=', maxsplit=1)
David James8c846492011-01-25 17:07:29 -080078 if file_key == key:
79 if val == file_val:
Sergey Frolov09280f12022-06-06 17:47:32 -060080 if entry_found:
81 self.fail(f'Variable {file_key} appears twice')
82 else:
83 entry_found = True
84
85 if not entry_found:
David James8c846492011-01-25 17:07:29 -080086 self.fail('Could not find "%s=%s" in version file' % (key, val))
87
88 def testAddVariableThatDoesNotExist(self):
89 """Add in a new variable that was no present in the file."""
90 key = 'PORTAGE_BINHOST'
91 value = '1234567'
92 prebuilt.UpdateLocalFile(self.version_file, value)
Mike Frysinger383367e2014-09-16 15:06:17 -040093 print(self.version_file)
Chris Sosa58669192011-06-30 12:45:03 -070094 self._read_version_file()
David James8c846492011-01-25 17:07:29 -080095 self._verify_key_pair(key, value)
Mike Frysinger383367e2014-09-16 15:06:17 -040096 print(self.version_file)
David James8c846492011-01-25 17:07:29 -080097
98 def testUpdateVariable(self):
99 """Test updating a variable that already exists."""
Sergey Frolov09280f12022-06-06 17:47:32 -0600100 binhost_key, binhost_val = self.contents_str[2].split('=')
101 if binhost_key != 'PORTAGE_BINHOST':
102 self.fail('unexpected test input: expected PORTAGE_BINHOST at line[2]')
103 self._verify_key_pair(binhost_key, binhost_val)
104
105 # Confirm that unrelated variable 'PKGDIR' does not change.
106 pkgdir_key, pkgdir_val = self.contents_str[1].split('=')
107 if pkgdir_key != 'PKGDIR':
108 self.fail('unexpected test input: expected PKGDIR at line[1]')
109 self._verify_key_pair(pkgdir_key, pkgdir_val)
110
111 binhost_new_val = 'test_update'
112 prebuilt.UpdateLocalFile(self.version_file, binhost_new_val)
113 self._verify_key_pair(binhost_key, binhost_new_val)
114 self._verify_key_pair(pkgdir_key, pkgdir_val)
115
116 binhost_new_val = 'test_update2'
117 prebuilt.UpdateLocalFile(self.version_file, binhost_new_val)
118 self._verify_key_pair(binhost_key, binhost_new_val)
119 self._verify_key_pair(pkgdir_key, pkgdir_val)
David James8c846492011-01-25 17:07:29 -0800120
121 def testUpdateNonExistentFile(self):
122 key = 'PORTAGE_BINHOST'
123 value = '1234567'
124 non_existent_file = tempfile.mktemp()
125 try:
126 prebuilt.UpdateLocalFile(non_existent_file, value)
127 file_contents = self._read_version_file(non_existent_file)
Chris Sosa739c8752012-05-16 19:30:35 -0700128 self.assertEqual(file_contents, ['%s="%s"' % (key, value)])
David James8c846492011-01-25 17:07:29 -0800129 finally:
130 if os.path.exists(non_existent_file):
131 os.remove(non_existent_file)
132
133
Mike Frysinger68182472014-11-05 22:38:39 -0500134class TestPrebuilt(cros_test_lib.MockTestCase):
Mike Frysingerc6824f62014-02-03 11:09:44 -0500135 """Tests for Prebuilt logic."""
David James8c846492011-01-25 17:07:29 -0800136
Bertrand SIMONNET811bcde2014-11-20 15:21:25 -0800137 def setUp(self):
Mike Nicholsd0acc7f2021-05-21 17:18:24 +0000138 self._base_local_path = '/b/cbuild/build/chroot/build/x86-dogfood/'
Bertrand SIMONNET811bcde2014-11-20 15:21:25 -0800139 self._gs_bucket_path = 'gs://chromeos-prebuilt/host/version'
140 self._local_path = os.path.join(self._base_local_path, 'public1.tbz2')
141
David James8c846492011-01-25 17:07:29 -0800142 def testGenerateUploadDict(self):
Mike Frysinger68182472014-11-05 22:38:39 -0500143 self.PatchObject(prebuilt.os.path, 'exists', return_true=True)
Mike Frysingerd6e2df02014-11-26 02:55:04 -0500144 pkgs = [{'CPV': 'public1'}]
Bertrand SIMONNET811bcde2014-11-20 15:21:25 -0800145 result = prebuilt.GenerateUploadDict(self._base_local_path,
146 self._gs_bucket_path, pkgs)
147 expected = {self._local_path: self._gs_bucket_path + '/public1.tbz2', }
148 self.assertEqual(result, expected)
149
150 def testGenerateUploadDictWithDebug(self):
151 self.PatchObject(prebuilt.os.path, 'exists', return_true=True)
152 pkgs = [{'CPV': 'public1', 'DEBUG_SYMBOLS': 'yes'}]
153 result = prebuilt.GenerateUploadDict(self._base_local_path,
154 self._gs_bucket_path, pkgs)
155 expected = {self._local_path: self._gs_bucket_path + '/public1.tbz2',
156 self._local_path.replace('.tbz2', '.debug.tbz2'):
157 self._gs_bucket_path + '/public1.debug.tbz2'}
David James8c846492011-01-25 17:07:29 -0800158 self.assertEqual(result, expected)
159
David James8c846492011-01-25 17:07:29 -0800160 def testDeterminePrebuiltConfHost(self):
161 """Test that the host prebuilt path comes back properly."""
162 expected_path = os.path.join(prebuilt._PREBUILT_MAKE_CONF['amd64'])
163 self.assertEqual(prebuilt.DeterminePrebuiltConfFile('fake_path', 'amd64'),
164 expected_path)
165
David James8c846492011-01-25 17:07:29 -0800166
David James2c7ccb42012-11-04 15:34:28 -0800167class TestPkgIndex(cros_test_lib.TestCase):
Mike Frysingerc6824f62014-02-03 11:09:44 -0500168 """Helper for tests that update the Packages index file."""
David James2c7ccb42012-11-04 15:34:28 -0800169
170 def setUp(self):
171 self.db = {}
172 self.pkgindex = SimplePackageIndex()
173 self.empty = SimplePackageIndex(packages=False)
174
175 def assertURIs(self, uris):
176 """Verify that the duplicate DB has the specified URLs."""
177 expected = [v.uri for _, v in sorted(self.db.items())]
178 self.assertEqual(expected, uris)
179
180
181class TestPackagesFileFiltering(TestPkgIndex):
Mike Frysingerc6824f62014-02-03 11:09:44 -0500182 """Tests for Packages filtering behavior."""
David James8c846492011-01-25 17:07:29 -0800183
184 def testFilterPkgIndex(self):
David James2c7ccb42012-11-04 15:34:28 -0800185 """Test filtering out of private packages."""
186 self.pkgindex.RemoveFilteredPackages(lambda pkg: pkg in PRIVATE_PACKAGES)
187 self.assertEqual(self.pkgindex.packages, PUBLIC_PACKAGES)
188 self.assertEqual(self.pkgindex.modified, True)
David James8c846492011-01-25 17:07:29 -0800189
190
David James2c7ccb42012-11-04 15:34:28 -0800191class TestPopulateDuplicateDB(TestPkgIndex):
Mike Frysingerc6824f62014-02-03 11:09:44 -0500192 """Tests for the _PopulateDuplicateDB function."""
David James8c846492011-01-25 17:07:29 -0800193
194 def testEmptyIndex(self):
David James2c7ccb42012-11-04 15:34:28 -0800195 """Test population of the duplicate DB with an empty index."""
196 self.empty._PopulateDuplicateDB(self.db, 0)
197 self.assertEqual(self.db, {})
David James8c846492011-01-25 17:07:29 -0800198
199 def testNormalIndex(self):
David James2c7ccb42012-11-04 15:34:28 -0800200 """Test population of the duplicate DB with a full index."""
201 self.pkgindex._PopulateDuplicateDB(self.db, 0)
202 self.assertURIs(['gs://example/gtk+/public1.tbz2',
203 'gs://example/gtk+/foo.tgz',
204 'gs://example/private.tbz2'])
David James8c846492011-01-25 17:07:29 -0800205
206 def testMissingSHA1(self):
David James2c7ccb42012-11-04 15:34:28 -0800207 """Test population of the duplicate DB with a missing SHA1."""
208 del self.pkgindex.packages[0]['SHA1']
209 self.pkgindex._PopulateDuplicateDB(self.db, 0)
210 self.assertURIs(['gs://example/gtk+/foo.tgz',
211 'gs://example/private.tbz2'])
David James8c846492011-01-25 17:07:29 -0800212
213 def testFailedPopulate(self):
David James2c7ccb42012-11-04 15:34:28 -0800214 """Test failure conditions for the populate method."""
215 headerless = SimplePackageIndex(header=False)
216 self.assertRaises(KeyError, headerless._PopulateDuplicateDB, self.db, 0)
217 del self.pkgindex.packages[0]['CPV']
218 self.assertRaises(KeyError, self.pkgindex._PopulateDuplicateDB, self.db, 0)
David James8c846492011-01-25 17:07:29 -0800219
220
Mike Frysinger68182472014-11-05 22:38:39 -0500221class TestResolveDuplicateUploads(cros_test_lib.MockTestCase, TestPkgIndex):
Mike Frysingerc6824f62014-02-03 11:09:44 -0500222 """Tests for the ResolveDuplicateUploads function."""
David James8c846492011-01-25 17:07:29 -0800223
David James615e5b52011-06-03 11:10:15 -0700224 def setUp(self):
Mike Frysinger68182472014-11-05 22:38:39 -0500225 self.PatchObject(binpkg.time, 'time', return_value=binpkg.TWO_WEEKS)
David James2c7ccb42012-11-04 15:34:28 -0800226 self.db = {}
227 self.dup = SimplePackageIndex()
228 self.expected_pkgindex = SimplePackageIndex()
229
230 def assertNoDuplicates(self, candidates):
231 """Verify no duplicates are found with the specified candidates."""
232 uploads = self.pkgindex.ResolveDuplicateUploads(candidates)
233 self.assertEqual(uploads, self.pkgindex.packages)
234 self.assertEqual(len(self.pkgindex.packages),
235 len(self.expected_pkgindex.packages))
236 for pkg1, pkg2 in zip(self.pkgindex.packages,
237 self.expected_pkgindex.packages):
238 self.assertNotEqual(pkg1['MTIME'], pkg2['MTIME'])
239 del pkg1['MTIME']
240 del pkg2['MTIME']
241 self.assertEqual(self.pkgindex.modified, False)
242 self.assertEqual(self.pkgindex.packages, self.expected_pkgindex.packages)
243
244 def assertAllDuplicates(self, candidates):
245 """Verify every package is a duplicate in the specified list."""
246 for pkg in self.expected_pkgindex.packages:
247 pkg.setdefault('PATH', pkg['CPV'] + '.tbz2')
248 self.pkgindex.ResolveDuplicateUploads(candidates)
249 self.assertEqual(self.pkgindex.packages, self.expected_pkgindex.packages)
David James615e5b52011-06-03 11:10:15 -0700250
David James8c846492011-01-25 17:07:29 -0800251 def testEmptyList(self):
David James2c7ccb42012-11-04 15:34:28 -0800252 """If no candidates are supplied, no duplicates should be found."""
253 self.assertNoDuplicates([])
David James8c846492011-01-25 17:07:29 -0800254
255 def testEmptyIndex(self):
David James2c7ccb42012-11-04 15:34:28 -0800256 """If no packages are supplied, no duplicates should be found."""
257 self.assertNoDuplicates([self.empty])
David James8c846492011-01-25 17:07:29 -0800258
David James2c7ccb42012-11-04 15:34:28 -0800259 def testDifferentURI(self):
260 """If the URI differs, no duplicates should be found."""
261 self.dup.header['URI'] = 'gs://example2'
262 self.assertNoDuplicates([self.dup])
263
264 def testUpdateModificationTime(self):
265 """When duplicates are found, we should use the latest mtime."""
266 for pkg in self.expected_pkgindex.packages:
267 pkg['MTIME'] = '10'
268 for pkg in self.dup.packages:
269 pkg['MTIME'] = '4'
270 self.assertAllDuplicates([self.expected_pkgindex, self.dup])
271
272 def testCanonicalUrl(self):
273 """If the URL is in a different format, we should still find duplicates."""
274 self.dup.header['URI'] = gs.PUBLIC_BASE_HTTPS_URL + 'example'
275 self.assertAllDuplicates([self.dup])
David James8c846492011-01-25 17:07:29 -0800276
277 def testMissingSHA1(self):
David James2c7ccb42012-11-04 15:34:28 -0800278 """We should not find duplicates if there is no SHA1."""
279 del self.pkgindex.packages[0]['SHA1']
280 del self.expected_pkgindex.packages[0]['SHA1']
281 for pkg in self.expected_pkgindex.packages[1:]:
David James8c846492011-01-25 17:07:29 -0800282 pkg.setdefault('PATH', pkg['CPV'] + '.tbz2')
David James2c7ccb42012-11-04 15:34:28 -0800283 self.pkgindex.ResolveDuplicateUploads([self.dup])
284 self.assertNotEqual(self.pkgindex.packages[0]['MTIME'],
285 self.expected_pkgindex.packages[0]['MTIME'])
286 del self.pkgindex.packages[0]['MTIME']
287 del self.expected_pkgindex.packages[0]['MTIME']
288 self.assertEqual(self.pkgindex.packages, self.expected_pkgindex.packages)
David James8c846492011-01-25 17:07:29 -0800289
Bertrand SIMONNET811bcde2014-11-20 15:21:25 -0800290 def testSymbolsAvailable(self):
291 """If symbols are available remotely, re-use them and set DEBUG_SYMBOLS."""
292 self.dup.packages[0]['DEBUG_SYMBOLS'] = 'yes'
293
294 uploads = self.pkgindex.ResolveDuplicateUploads([self.dup])
295 self.assertEqual(uploads, [])
296 self.assertEqual(self.pkgindex.packages[0].get('DEBUG_SYMBOLS'), 'yes')
297
298 def testSymbolsAvailableLocallyOnly(self):
299 """If the symbols are only available locally, reupload them."""
300 self.pkgindex.packages[0]['DEBUG_SYMBOLS'] = 'yes'
301
302 uploads = self.pkgindex.ResolveDuplicateUploads([self.dup])
303 self.assertEqual(uploads, [self.pkgindex.packages[0]])
304
David James8c846492011-01-25 17:07:29 -0800305
Mike Frysinger68182472014-11-05 22:38:39 -0500306class TestWritePackageIndex(cros_test_lib.MockTestCase, TestPkgIndex):
Mike Frysingerc6824f62014-02-03 11:09:44 -0500307 """Tests for the WriteToNamedTemporaryFile function."""
David James8c846492011-01-25 17:07:29 -0800308
309 def testSimple(self):
David James2c7ccb42012-11-04 15:34:28 -0800310 """Test simple call of WriteToNamedTemporaryFile()"""
Mike Frysinger68182472014-11-05 22:38:39 -0500311 self.PatchObject(self.pkgindex, 'Write')
David James2c7ccb42012-11-04 15:34:28 -0800312 f = self.pkgindex.WriteToNamedTemporaryFile()
Mike Frysinger652057c2019-12-09 23:59:07 -0500313 self.assertEqual(f.read(), '')
David James8c846492011-01-25 17:07:29 -0800314
315
Mike Frysinger36870f92015-04-12 02:59:55 -0400316class TestUploadPrebuilt(cros_test_lib.MockTempDirTestCase):
Mike Frysingerc6824f62014-02-03 11:09:44 -0500317 """Tests for the _UploadPrebuilt function."""
David James05bcb2b2011-02-09 09:25:47 -0800318
319 def setUp(self):
320 class MockTemporaryFile(object):
Mike Frysingerc6824f62014-02-03 11:09:44 -0500321 """Mock out the temporary file logic."""
David James05bcb2b2011-02-09 09:25:47 -0800322 def __init__(self, name):
323 self.name = name
David James05bcb2b2011-02-09 09:25:47 -0800324 self.pkgindex = SimplePackageIndex()
Mike Frysinger36870f92015-04-12 02:59:55 -0400325 self.PatchObject(binpkg, 'GrabLocalPackageIndex',
326 return_value=self.pkgindex)
327 self.PatchObject(self.pkgindex, 'ResolveDuplicateUploads',
328 return_value=PRIVATE_PACKAGES)
329 self.PatchObject(self.pkgindex, 'WriteToNamedTemporaryFile',
330 return_value=MockTemporaryFile('fake'))
331 self.remote_up_mock = self.PatchObject(prebuilt, 'RemoteUpload')
332 self.gs_up_mock = self.PatchObject(prebuilt, '_GsUpload')
David James05bcb2b2011-02-09 09:25:47 -0800333
David James05bcb2b2011-02-09 09:25:47 -0800334 def testSuccessfulGsUpload(self):
Alex Deymo541ea6f2014-12-23 01:18:14 -0800335 uploads = {
336 os.path.join(self.tempdir, 'private.tbz2'): 'gs://foo/private.tbz2'}
Mike Frysinger9bb6cd82020-08-20 03:02:23 -0400337 dev_extras = os.path.join(self.tempdir, 'dev-only-extras.tar.xz')
338 osutils.Touch(dev_extras)
Mike Frysinger36870f92015-04-12 02:59:55 -0400339 self.PatchObject(prebuilt, 'GenerateUploadDict',
340 return_value=uploads)
David James05bcb2b2011-02-09 09:25:47 -0800341 uploads = uploads.copy()
342 uploads['fake'] = 'gs://foo/suffix/Packages'
Mike Frysinger9bb6cd82020-08-20 03:02:23 -0400343 uploads[dev_extras] = 'gs://foo/suffix/dev-only-extras.tar.xz'
David Jamesfd0b0852011-02-23 11:15:36 -0800344 acl = 'public-read'
David Jamesc0f158a2011-02-22 16:07:29 -0800345 uri = self.pkgindex.header['URI']
David James8ece7ee2011-06-29 16:02:30 -0700346 uploader = prebuilt.PrebuiltUploader('gs://foo', acl, uri, [], '/', [],
Mike Frysinger8092a632014-05-24 13:25:46 -0400347 False, 'foo', False, 'x86-foo', [], '')
Alex Deymo541ea6f2014-12-23 01:18:14 -0800348 uploader._UploadPrebuilt(self.tempdir, 'suffix')
Mike Frysinger36870f92015-04-12 02:59:55 -0400349 self.remote_up_mock.assert_called_once_with(mock.ANY, acl, uploads)
350 self.assertTrue(self.gs_up_mock.called)
David James05bcb2b2011-02-09 09:25:47 -0800351
David James05bcb2b2011-02-09 09:25:47 -0800352
Mike Frysinger36870f92015-04-12 02:59:55 -0400353class TestSyncPrebuilts(cros_test_lib.MockTestCase):
Mike Frysingerc6824f62014-02-03 11:09:44 -0500354 """Tests for the SyncHostPrebuilts function."""
David James05bcb2b2011-02-09 09:25:47 -0800355
356 def setUp(self):
Mike Frysinger36870f92015-04-12 02:59:55 -0400357 self.rev_mock = self.PatchObject(prebuilt, 'RevGitFile', return_value=None)
358 self.update_binhost_mock = self.PatchObject(
359 prebuilt, 'UpdateBinhostConfFile', return_value=None)
David James05bcb2b2011-02-09 09:25:47 -0800360 self.build_path = '/trunk'
361 self.upload_location = 'gs://upload/'
362 self.version = '1'
363 self.binhost = 'http://prebuilt/'
364 self.key = 'PORTAGE_BINHOST'
Mike Frysinger36870f92015-04-12 02:59:55 -0400365 self.upload_mock = self.PatchObject(prebuilt.PrebuiltUploader,
366 '_UploadPrebuilt', return_value=True)
David James05bcb2b2011-02-09 09:25:47 -0800367
Bob Haarmand1225ea2022-01-19 22:01:42 +0000368 def _testSyncHostPrebuilts(self, chroot):
David Jamese2488642011-11-14 16:15:20 -0800369 board = 'x86-foo'
David James4058b0d2011-12-08 21:24:50 -0800370 target = prebuilt.BuildTarget(board, 'aura')
371 slave_targets = [prebuilt.BuildTarget('x86-bar', 'aura')]
Bob Haarmand1225ea2022-01-19 22:01:42 +0000372 if chroot is None:
373 package_path = os.path.join(self.build_path,
374 'chroot',
375 prebuilt._HOST_PACKAGES_PATH)
376 else:
377 package_path = os.path.join(chroot, prebuilt._HOST_PACKAGES_PATH)
Mike Frysingerd6e2df02014-11-26 02:55:04 -0500378 url_suffix = prebuilt._REL_HOST_PATH % {
379 'version': self.version,
380 'host_arch': prebuilt._HOST_ARCH,
381 'target': target,
382 }
David James8fa34ea2011-04-15 13:00:20 -0700383 packages_url_suffix = '%s/packages' % url_suffix.rstrip('/')
David Jamesf0e6fd72011-04-15 15:58:07 -0700384 url_value = '%s/%s/' % (self.binhost.rstrip('/'),
385 packages_url_suffix.rstrip('/'))
David Jamese2488642011-11-14 16:15:20 -0800386 urls = [url_value.replace('foo', 'bar'), url_value]
David James20b2b6f2011-11-18 15:11:58 -0800387 binhost = ' '.join(urls)
David James615e5b52011-06-03 11:10:15 -0700388 uploader = prebuilt.PrebuiltUploader(
389 self.upload_location, 'public-read', self.binhost, [],
Mike Frysinger8092a632014-05-24 13:25:46 -0400390 self.build_path, [], False, 'foo', False, target, slave_targets,
Bob Haarmand1225ea2022-01-19 22:01:42 +0000391 self.version, chroot=chroot)
Mike Frysinger8092a632014-05-24 13:25:46 -0400392 uploader.SyncHostPrebuilts(self.key, True, True)
Mike Frysinger36870f92015-04-12 02:59:55 -0400393 self.upload_mock.assert_called_once_with(package_path, packages_url_suffix)
394 self.rev_mock.assert_called_once_with(
395 mock.ANY, {self.key: binhost}, dryrun=False)
396 self.update_binhost_mock.assert_called_once_with(
397 mock.ANY, self.key, binhost)
David James05bcb2b2011-02-09 09:25:47 -0800398
Bob Haarmand1225ea2022-01-19 22:01:42 +0000399 def testSyncHostPrebuilts(self):
400 self._testSyncHostPrebuilts(chroot=None)
401
402 def testSyncHostPrebuiltsWithChroot(self):
403 self._testSyncHostPrebuilts('/test/chroot')
404
David James05bcb2b2011-02-09 09:25:47 -0800405 def testSyncBoardPrebuilts(self):
David Jamese2488642011-11-14 16:15:20 -0800406 board = 'x86-foo'
David James4058b0d2011-12-08 21:24:50 -0800407 target = prebuilt.BuildTarget(board, 'aura')
408 slave_targets = [prebuilt.BuildTarget('x86-bar', 'aura')]
Mike Frysinger8092a632014-05-24 13:25:46 -0400409 board_path = os.path.join(
410 self.build_path, prebuilt._BOARD_PATH % {'board': board})
David James05bcb2b2011-02-09 09:25:47 -0800411 package_path = os.path.join(board_path, 'packages')
Mike Frysingerd6e2df02014-11-26 02:55:04 -0500412 url_suffix = prebuilt._REL_BOARD_PATH % {
413 'version': self.version,
414 'target': target,
415 }
David James8fa34ea2011-04-15 13:00:20 -0700416 packages_url_suffix = '%s/packages' % url_suffix.rstrip('/')
David Jamesf0e6fd72011-04-15 15:58:07 -0700417 url_value = '%s/%s/' % (self.binhost.rstrip('/'),
418 packages_url_suffix.rstrip('/'))
David Jamese2488642011-11-14 16:15:20 -0800419 bar_binhost = url_value.replace('foo', 'bar')
Mike Frysinger36870f92015-04-12 02:59:55 -0400420 determine_mock = self.PatchObject(prebuilt, 'DeterminePrebuiltConfFile',
421 side_effect=('bar', 'foo'))
422 self.PatchObject(prebuilt.PrebuiltUploader, '_UploadSdkTarball')
423 with parallel_unittest.ParallelMock():
424 multiprocessing.Process.exitcode = 0
425 uploader = prebuilt.PrebuiltUploader(
426 self.upload_location, 'public-read', self.binhost, [],
427 self.build_path, [], False, 'foo', False, target, slave_targets,
428 self.version)
Gilad Arnoldad333182015-05-27 15:50:41 -0700429 uploader.SyncBoardPrebuilts(self.key, True, True, True, None, None, None,
430 None, None)
Mike Frysinger36870f92015-04-12 02:59:55 -0400431 determine_mock.assert_has_calls([
432 mock.call(self.build_path, slave_targets[0]),
433 mock.call(self.build_path, target),
434 ])
435 self.upload_mock.assert_called_once_with(package_path, packages_url_suffix)
436 self.rev_mock.assert_has_calls([
437 mock.call('bar', {self.key: bar_binhost}, dryrun=False),
438 mock.call('foo', {self.key: url_value}, dryrun=False),
439 ])
440 self.update_binhost_mock.assert_has_calls([
441 mock.call(mock.ANY, self.key, bar_binhost),
442 mock.call(mock.ANY, self.key, url_value),
443 ])
David James05bcb2b2011-02-09 09:25:47 -0800444
445
Mike Frysinger36870f92015-04-12 02:59:55 -0400446class TestMain(cros_test_lib.MockTestCase):
Mike Frysingerc6824f62014-02-03 11:09:44 -0500447 """Tests for the main() function."""
David Jamesc0f158a2011-02-22 16:07:29 -0800448
449 def testMain(self):
450 """Test that the main function works."""
Mike Frysinger36870f92015-04-12 02:59:55 -0400451 options = mock.MagicMock()
David Jamesc0f158a2011-02-22 16:07:29 -0800452 old_binhost = 'http://prebuilt/1'
453 options.previous_binhost_url = [old_binhost]
David Jamese2488642011-11-14 16:15:20 -0800454 options.board = 'x86-foo'
David James4058b0d2011-12-08 21:24:50 -0800455 options.profile = None
Chris Sosa6a5dceb2012-05-14 13:48:56 -0700456 target = prebuilt.BuildTarget(options.board, options.profile)
David Jamesc0f158a2011-02-22 16:07:29 -0800457 options.build_path = '/trunk'
Bob Haarmand1225ea2022-01-19 22:01:42 +0000458 options.chroot = None
Mike Frysinger86509232014-05-24 13:18:37 -0400459 options.dryrun = False
David Jamesfd0b0852011-02-23 11:15:36 -0800460 options.private = True
David James615e5b52011-06-03 11:10:15 -0700461 options.packages = []
David Jamesc0f158a2011-02-22 16:07:29 -0800462 options.sync_host = True
463 options.git_sync = True
David James8fa34ea2011-04-15 13:00:20 -0700464 options.upload_board_tarball = True
Zdenek Behan62a57792012-08-31 15:09:08 +0200465 options.prepackaged_tarball = None
Gilad Arnold2b79e2d2015-06-02 11:26:07 -0700466 options.toolchains_overlay_tarballs = []
467 options.toolchains_overlay_upload_path = ''
Mike Frysinger9e979b92012-11-29 02:55:09 -0500468 options.toolchain_tarballs = []
469 options.toolchain_upload_path = ''
David Jamesc0f158a2011-02-22 16:07:29 -0800470 options.upload = 'gs://upload/'
David Jamesfd0b0852011-02-23 11:15:36 -0800471 options.binhost_base_url = options.upload
David Jamesc0f158a2011-02-22 16:07:29 -0800472 options.prepend_version = True
David James8ece7ee2011-06-29 16:02:30 -0700473 options.set_version = None
474 options.skip_upload = False
David Jamesc0f158a2011-02-22 16:07:29 -0800475 options.filters = True
476 options.key = 'PORTAGE_BINHOST'
David Jamesb26b9312014-12-15 11:26:46 -0800477 options.binhost_conf_dir = None
David Jamesc0f158a2011-02-22 16:07:29 -0800478 options.sync_binhost_conf = True
David James4058b0d2011-12-08 21:24:50 -0800479 options.slave_targets = [prebuilt.BuildTarget('x86-bar', 'aura')]
Mike Frysinger36870f92015-04-12 02:59:55 -0400480 self.PatchObject(prebuilt, 'ParseOptions',
481 return_value=tuple([options, target]))
482 self.PatchObject(binpkg, 'GrabRemotePackageIndex', return_value=True)
483 init_mock = self.PatchObject(prebuilt.PrebuiltUploader, '__init__',
484 return_value=None)
485 expected_gs_acl_path = os.path.join('/fake_path',
Prathmesh Prabhu5f14da02014-10-17 15:13:56 -0700486 prebuilt._GOOGLESTORAGE_GSUTIL_FILE)
Mike Frysinger36870f92015-04-12 02:59:55 -0400487 self.PatchObject(portage_util, 'FindOverlayFile',
488 return_value=expected_gs_acl_path)
489 host_mock = self.PatchObject(
490 prebuilt.PrebuiltUploader, 'SyncHostPrebuilts', return_value=None)
491 board_mock = self.PatchObject(
492 prebuilt.PrebuiltUploader, 'SyncBoardPrebuilts', return_value=None)
493
494 prebuilt.main([])
495
496 init_mock.assert_called_once_with(options.upload, expected_gs_acl_path,
497 options.upload, mock.ANY,
498 options.build_path, options.packages,
499 False, None, False,
500 target, options.slave_targets,
Bob Haarmand1225ea2022-01-19 22:01:42 +0000501 mock.ANY, None)
Mike Frysinger36870f92015-04-12 02:59:55 -0400502 board_mock.assert_called_once_with(
Mike Frysinger8092a632014-05-24 13:25:46 -0400503 options.key, options.git_sync,
Gilad Arnoldad333182015-05-27 15:50:41 -0700504 options.sync_binhost_conf, options.upload_board_tarball, None,
505 [], '', [], '')
Mike Frysinger36870f92015-04-12 02:59:55 -0400506 host_mock.assert_called_once_with(
507 options.key, options.git_sync, options.sync_binhost_conf)
David Jamesc0f158a2011-02-22 16:07:29 -0800508
Mike Frysinger9e979b92012-11-29 02:55:09 -0500509
Mike Frysinger68182472014-11-05 22:38:39 -0500510class TestSdk(cros_test_lib.MockTestCase):
Mike Frysinger9e979b92012-11-29 02:55:09 -0500511 """Test logic related to uploading SDK binaries"""
512
513 def setUp(self):
Mike Frysinger68182472014-11-05 22:38:39 -0500514 self.PatchObject(prebuilt, '_GsUpload',
515 side_effect=Exception('should not get called'))
516 self.PatchObject(prebuilt, 'UpdateBinhostConfFile',
517 side_effect=Exception('should not get called'))
518 self.upload_mock = self.PatchObject(prebuilt.PrebuiltUploader, '_Upload')
Mike Frysinger9e979b92012-11-29 02:55:09 -0500519
520 self.acl = 'magic-acl'
521
522 # All these args pretty much get ignored. Whee.
523 self.uploader = prebuilt.PrebuiltUploader(
524 'gs://foo', self.acl, 'prebuilt', [], '/', [],
Mike Frysinger8092a632014-05-24 13:25:46 -0400525 False, 'foo', False, 'x86-foo', [], 'chroot-1234')
Mike Frysinger9e979b92012-11-29 02:55:09 -0500526
Gilad Arnold2b79e2d2015-06-02 11:26:07 -0700527 def testSdkUpload(self, to_tarballs=(), to_upload_path=None,
Gilad Arnoldad333182015-05-27 15:50:41 -0700528 tc_tarballs=(), tc_upload_path=None):
Mike Frysinger9e979b92012-11-29 02:55:09 -0500529 """Make sure we can upload just an SDK tarball"""
530 tar = 'sdk.tar.xz'
531 ver = '1234'
532 vtar = 'cros-sdk-%s.tar.xz' % ver
533
Mike Frysinger68182472014-11-05 22:38:39 -0500534 calls = [
535 mock.call('%s.Manifest' % tar,
536 'gs://chromiumos-sdk/%s.Manifest' % vtar),
537 mock.call(tar, 'gs://chromiumos-sdk/%s' % vtar),
538 ]
Gilad Arnold2b79e2d2015-06-02 11:26:07 -0700539 for to in to_tarballs:
540 to = to.split(':')
Gilad Arnoldad333182015-05-27 15:50:41 -0700541 calls.append(mock.call(
Gilad Arnold2b79e2d2015-06-02 11:26:07 -0700542 to[1],
543 ('gs://chromiumos-sdk/' + to_upload_path) % {'toolchains': to[0]}))
Mike Frysinger68182472014-11-05 22:38:39 -0500544 for tc in tc_tarballs:
545 tc = tc.split(':')
546 calls.append(mock.call(
547 tc[1], ('gs://chromiumos-sdk/' + tc_upload_path) % {'target': tc[0]}))
548 calls.append(mock.call(
549 mock.ANY, 'gs://chromiumos-sdk/cros-sdk-latest.conf'))
Mike Frysinger9e979b92012-11-29 02:55:09 -0500550
Mike Frysinger8092a632014-05-24 13:25:46 -0400551 self.uploader._UploadSdkTarball('amd64-host', '',
Gilad Arnold2b79e2d2015-06-02 11:26:07 -0700552 tar, to_tarballs, to_upload_path,
Gilad Arnoldad333182015-05-27 15:50:41 -0700553 tc_tarballs, tc_upload_path)
Mike Frysinger68182472014-11-05 22:38:39 -0500554 self.upload_mock.assert_has_calls(calls)
Mike Frysinger9e979b92012-11-29 02:55:09 -0500555
Gilad Arnoldad333182015-05-27 15:50:41 -0700556 def testBoardOverlayTarballUpload(self):
557 """Make sure processing of board-specific overlay tarballs works."""
Gilad Arnold2b79e2d2015-06-02 11:26:07 -0700558 to_tarballs = (
559 ('i686-pc-linux-gnu:'
560 '/some/path/built-sdk-overlay-toolchains-i686-pc-linux-gnu.tar.xz'),
561 ('armv7a-cros-linux-gnueabi-arm-none-eabi:'
562 '/some/path/built-sdk-overlay-toolchains-armv7a-cros-linux-gnueabi-'
563 'arm-none-eabi'),
Gilad Arnoldad333182015-05-27 15:50:41 -0700564 )
Gilad Arnold2b79e2d2015-06-02 11:26:07 -0700565 to_upload_path = (
566 '1994/04/cros-sdk-overlay-toolchains-%(toolchains)s-1994.04.02.tar.xz')
567 self.testSdkUpload(to_tarballs=to_tarballs, to_upload_path=to_upload_path)
Gilad Arnoldad333182015-05-27 15:50:41 -0700568
569 def testToolchainTarballUpload(self):
570 """Make sure processing of toolchain tarballs works."""
Mike Frysinger9e979b92012-11-29 02:55:09 -0500571 tc_tarballs = (
572 'i686:/some/i686.tar.xz',
573 'arm-none:/some/arm.tar.xz',
574 )
575 tc_upload_path = '1994/04/%(target)s-1994.04.02.tar.xz'
Gilad Arnoldad333182015-05-27 15:50:41 -0700576 self.testSdkUpload(tc_tarballs=tc_tarballs, tc_upload_path=tc_upload_path)