blob: dc671194a039bdb2eadad38a08102f087aa30786 [file] [log] [blame]
Mike Frysingerf1ba7ad2022-09-12 05:42:57 -04001# Copyright 2012 The ChromiumOS Authors
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
Mike Frysinger166fea02021-02-12 05:30:33 -050010from unittest import mock
Chris Sosa471532a2011-02-01 15:10:06 -080011
Mike Frysinger40ffb532021-02-12 07:36:08 -050012from chromite.lib import binpkg
Brian Harringc92788f2012-09-21 18:07:15 -070013from chromite.lib import cros_test_lib
David James2c7ccb42012-11-04 15:34:28 -080014from chromite.lib import gs
Zdenek Behanc0e18762012-09-22 04:06:17 +020015from chromite.lib import osutils
Mike Frysinger36870f92015-04-12 02:59:55 -040016from chromite.lib import parallel_unittest
Prathmesh Prabhu421eef22014-10-16 17:13:19 -070017from chromite.lib import portage_util
Mike Frysinger40ffb532021-02-12 07:36:08 -050018from chromite.scripts import upload_prebuilts as prebuilt
David James8c846492011-01-25 17:07:29 -080019
Mike Frysinger68182472014-11-05 22:38:39 -050020
Mike Frysinger27e21b72018-07-12 14:20:21 -040021# pylint: disable=protected-access
22
23
Alex Klein1699fab2022-09-08 08:46:06 -060024PUBLIC_PACKAGES = [
25 {"CPV": "gtk+/public1", "SHA1": "1", "MTIME": "1"},
26 {"CPV": "gtk+/public2", "SHA1": "2", "PATH": "gtk+/foo.tgz", "MTIME": "2"},
27]
28PRIVATE_PACKAGES = [{"CPV": "private", "SHA1": "3", "MTIME": "3"}]
David James8c846492011-01-25 17:07:29 -080029
30
31def SimplePackageIndex(header=True, packages=True):
Alex Klein1699fab2022-09-08 08:46:06 -060032 pkgindex = binpkg.PackageIndex()
33 if header:
34 pkgindex.header["URI"] = "gs://example"
35 if packages:
36 pkgindex.packages = copy.deepcopy(PUBLIC_PACKAGES + PRIVATE_PACKAGES)
37 return pkgindex
David James8c846492011-01-25 17:07:29 -080038
39
Mike Frysinger68182472014-11-05 22:38:39 -050040class TestPrebuilt(cros_test_lib.MockTestCase):
Alex Klein1699fab2022-09-08 08:46:06 -060041 """Tests for Prebuilt logic."""
David James8c846492011-01-25 17:07:29 -080042
Alex Klein1699fab2022-09-08 08:46:06 -060043 def setUp(self):
44 self._base_local_path = "/b/cbuild/build/chroot/build/x86-dogfood/"
45 self._gs_bucket_path = "gs://chromeos-prebuilt/host/version"
46 self._local_path = os.path.join(self._base_local_path, "public1.tbz2")
Bertrand SIMONNET811bcde2014-11-20 15:21:25 -080047
Alex Klein1699fab2022-09-08 08:46:06 -060048 def testGenerateUploadDict(self):
49 self.PatchObject(prebuilt.os.path, "exists", return_true=True)
50 pkgs = [{"CPV": "public1"}]
51 result = prebuilt.GenerateUploadDict(
52 self._base_local_path, self._gs_bucket_path, pkgs
53 )
54 expected = {
55 self._local_path: self._gs_bucket_path + "/public1.tbz2",
56 }
57 self.assertEqual(result, expected)
Bertrand SIMONNET811bcde2014-11-20 15:21:25 -080058
Alex Klein1699fab2022-09-08 08:46:06 -060059 def testGenerateUploadDictWithDebug(self):
60 self.PatchObject(prebuilt.os.path, "exists", return_true=True)
61 pkgs = [{"CPV": "public1", "DEBUG_SYMBOLS": "yes"}]
62 result = prebuilt.GenerateUploadDict(
63 self._base_local_path, self._gs_bucket_path, pkgs
64 )
65 expected = {
66 self._local_path: self._gs_bucket_path + "/public1.tbz2",
67 self._local_path.replace(
68 ".tbz2", ".debug.tbz2"
69 ): self._gs_bucket_path
70 + "/public1.debug.tbz2",
71 }
72 self.assertEqual(result, expected)
David James8c846492011-01-25 17:07:29 -080073
Alex Klein1699fab2022-09-08 08:46:06 -060074 def testDeterminePrebuiltConfHost(self):
75 """Test that the host prebuilt path comes back properly."""
76 expected_path = os.path.join(prebuilt._PREBUILT_MAKE_CONF["amd64"])
77 self.assertEqual(
78 prebuilt.DeterminePrebuiltConfFile("fake_path", "amd64"),
79 expected_path,
80 )
David James8c846492011-01-25 17:07:29 -080081
David James8c846492011-01-25 17:07:29 -080082
David James2c7ccb42012-11-04 15:34:28 -080083class TestPkgIndex(cros_test_lib.TestCase):
Alex Klein1699fab2022-09-08 08:46:06 -060084 """Helper for tests that update the Packages index file."""
David James2c7ccb42012-11-04 15:34:28 -080085
Alex Klein1699fab2022-09-08 08:46:06 -060086 def setUp(self):
87 self.db = {}
88 self.pkgindex = SimplePackageIndex()
89 self.empty = SimplePackageIndex(packages=False)
David James2c7ccb42012-11-04 15:34:28 -080090
Alex Klein1699fab2022-09-08 08:46:06 -060091 def assertURIs(self, uris):
92 """Verify that the duplicate DB has the specified URLs."""
93 expected = [v.uri for _, v in sorted(self.db.items())]
94 self.assertEqual(expected, uris)
David James2c7ccb42012-11-04 15:34:28 -080095
96
97class TestPackagesFileFiltering(TestPkgIndex):
Alex Klein1699fab2022-09-08 08:46:06 -060098 """Tests for Packages filtering behavior."""
David James8c846492011-01-25 17:07:29 -080099
Alex Klein1699fab2022-09-08 08:46:06 -0600100 def testFilterPkgIndex(self):
101 """Test filtering out of private packages."""
102 self.pkgindex.RemoveFilteredPackages(
103 lambda pkg: pkg in PRIVATE_PACKAGES
104 )
105 self.assertEqual(self.pkgindex.packages, PUBLIC_PACKAGES)
106 self.assertEqual(self.pkgindex.modified, True)
David James8c846492011-01-25 17:07:29 -0800107
108
David James2c7ccb42012-11-04 15:34:28 -0800109class TestPopulateDuplicateDB(TestPkgIndex):
Alex Klein1699fab2022-09-08 08:46:06 -0600110 """Tests for the _PopulateDuplicateDB function."""
David James8c846492011-01-25 17:07:29 -0800111
Alex Klein1699fab2022-09-08 08:46:06 -0600112 def testEmptyIndex(self):
113 """Test population of the duplicate DB with an empty index."""
114 self.empty._PopulateDuplicateDB(self.db, 0)
115 self.assertEqual(self.db, {})
David James8c846492011-01-25 17:07:29 -0800116
Alex Klein1699fab2022-09-08 08:46:06 -0600117 def testNormalIndex(self):
118 """Test population of the duplicate DB with a full index."""
119 self.pkgindex._PopulateDuplicateDB(self.db, 0)
120 self.assertURIs(
121 [
122 "gs://example/gtk+/public1.tbz2",
123 "gs://example/gtk+/foo.tgz",
124 "gs://example/private.tbz2",
125 ]
126 )
David James8c846492011-01-25 17:07:29 -0800127
Alex Klein1699fab2022-09-08 08:46:06 -0600128 def testMissingSHA1(self):
129 """Test population of the duplicate DB with a missing SHA1."""
130 del self.pkgindex.packages[0]["SHA1"]
131 self.pkgindex._PopulateDuplicateDB(self.db, 0)
132 self.assertURIs(
133 ["gs://example/gtk+/foo.tgz", "gs://example/private.tbz2"]
134 )
David James8c846492011-01-25 17:07:29 -0800135
Alex Klein1699fab2022-09-08 08:46:06 -0600136 def testFailedPopulate(self):
137 """Test failure conditions for the populate method."""
138 headerless = SimplePackageIndex(header=False)
139 self.assertRaises(KeyError, headerless._PopulateDuplicateDB, self.db, 0)
140 del self.pkgindex.packages[0]["CPV"]
141 self.assertRaises(
142 KeyError, self.pkgindex._PopulateDuplicateDB, self.db, 0
143 )
David James8c846492011-01-25 17:07:29 -0800144
145
Mike Frysinger68182472014-11-05 22:38:39 -0500146class TestResolveDuplicateUploads(cros_test_lib.MockTestCase, TestPkgIndex):
Alex Klein1699fab2022-09-08 08:46:06 -0600147 """Tests for the ResolveDuplicateUploads function."""
David James8c846492011-01-25 17:07:29 -0800148
Alex Klein1699fab2022-09-08 08:46:06 -0600149 def setUp(self):
150 self.PatchObject(binpkg.time, "time", return_value=binpkg.TWO_WEEKS)
151 self.db = {}
152 self.dup = SimplePackageIndex()
153 self.expected_pkgindex = SimplePackageIndex()
David James2c7ccb42012-11-04 15:34:28 -0800154
Alex Klein1699fab2022-09-08 08:46:06 -0600155 def assertNoDuplicates(self, candidates):
156 """Verify no duplicates are found with the specified candidates."""
157 uploads = self.pkgindex.ResolveDuplicateUploads(candidates)
158 self.assertEqual(uploads, self.pkgindex.packages)
159 self.assertEqual(
160 len(self.pkgindex.packages), len(self.expected_pkgindex.packages)
161 )
162 for pkg1, pkg2 in zip(
163 self.pkgindex.packages, self.expected_pkgindex.packages
164 ):
165 self.assertNotEqual(pkg1["MTIME"], pkg2["MTIME"])
166 del pkg1["MTIME"]
167 del pkg2["MTIME"]
168 self.assertEqual(self.pkgindex.modified, False)
169 self.assertEqual(
170 self.pkgindex.packages, self.expected_pkgindex.packages
171 )
David James2c7ccb42012-11-04 15:34:28 -0800172
Alex Klein1699fab2022-09-08 08:46:06 -0600173 def assertAllDuplicates(self, candidates):
174 """Verify every package is a duplicate in the specified list."""
175 for pkg in self.expected_pkgindex.packages:
176 pkg.setdefault("PATH", pkg["CPV"] + ".tbz2")
177 self.pkgindex.ResolveDuplicateUploads(candidates)
178 self.assertEqual(
179 self.pkgindex.packages, self.expected_pkgindex.packages
180 )
David James615e5b52011-06-03 11:10:15 -0700181
Alex Klein1699fab2022-09-08 08:46:06 -0600182 def testEmptyList(self):
183 """If no candidates are supplied, no duplicates should be found."""
184 self.assertNoDuplicates([])
David James8c846492011-01-25 17:07:29 -0800185
Alex Klein1699fab2022-09-08 08:46:06 -0600186 def testEmptyIndex(self):
187 """If no packages are supplied, no duplicates should be found."""
188 self.assertNoDuplicates([self.empty])
David James8c846492011-01-25 17:07:29 -0800189
Alex Klein1699fab2022-09-08 08:46:06 -0600190 def testDifferentURI(self):
191 """If the URI differs, no duplicates should be found."""
192 self.dup.header["URI"] = "gs://example2"
193 self.assertNoDuplicates([self.dup])
David James2c7ccb42012-11-04 15:34:28 -0800194
Alex Klein1699fab2022-09-08 08:46:06 -0600195 def testUpdateModificationTime(self):
196 """When duplicates are found, we should use the latest mtime."""
197 for pkg in self.expected_pkgindex.packages:
198 pkg["MTIME"] = "10"
199 for pkg in self.dup.packages:
200 pkg["MTIME"] = "4"
201 self.assertAllDuplicates([self.expected_pkgindex, self.dup])
David James2c7ccb42012-11-04 15:34:28 -0800202
Alex Klein1699fab2022-09-08 08:46:06 -0600203 def testCanonicalUrl(self):
204 """If the URL is in a different format, we should still find duplicates."""
205 self.dup.header["URI"] = gs.PUBLIC_BASE_HTTPS_URL + "example"
206 self.assertAllDuplicates([self.dup])
David James8c846492011-01-25 17:07:29 -0800207
Alex Klein1699fab2022-09-08 08:46:06 -0600208 def testMissingSHA1(self):
209 """We should not find duplicates if there is no SHA1."""
210 del self.pkgindex.packages[0]["SHA1"]
211 del self.expected_pkgindex.packages[0]["SHA1"]
212 for pkg in self.expected_pkgindex.packages[1:]:
213 pkg.setdefault("PATH", pkg["CPV"] + ".tbz2")
214 self.pkgindex.ResolveDuplicateUploads([self.dup])
215 self.assertNotEqual(
216 self.pkgindex.packages[0]["MTIME"],
217 self.expected_pkgindex.packages[0]["MTIME"],
218 )
219 del self.pkgindex.packages[0]["MTIME"]
220 del self.expected_pkgindex.packages[0]["MTIME"]
221 self.assertEqual(
222 self.pkgindex.packages, self.expected_pkgindex.packages
223 )
David James8c846492011-01-25 17:07:29 -0800224
Alex Klein1699fab2022-09-08 08:46:06 -0600225 def testSymbolsAvailable(self):
226 """If symbols are available remotely, re-use them and set DEBUG_SYMBOLS."""
227 self.dup.packages[0]["DEBUG_SYMBOLS"] = "yes"
Bertrand SIMONNET811bcde2014-11-20 15:21:25 -0800228
Alex Klein1699fab2022-09-08 08:46:06 -0600229 uploads = self.pkgindex.ResolveDuplicateUploads([self.dup])
230 self.assertEqual(uploads, [])
231 self.assertEqual(self.pkgindex.packages[0].get("DEBUG_SYMBOLS"), "yes")
Bertrand SIMONNET811bcde2014-11-20 15:21:25 -0800232
Alex Klein1699fab2022-09-08 08:46:06 -0600233 def testSymbolsAvailableLocallyOnly(self):
234 """If the symbols are only available locally, reupload them."""
235 self.pkgindex.packages[0]["DEBUG_SYMBOLS"] = "yes"
Bertrand SIMONNET811bcde2014-11-20 15:21:25 -0800236
Alex Klein1699fab2022-09-08 08:46:06 -0600237 uploads = self.pkgindex.ResolveDuplicateUploads([self.dup])
238 self.assertEqual(uploads, [self.pkgindex.packages[0]])
Bertrand SIMONNET811bcde2014-11-20 15:21:25 -0800239
David James8c846492011-01-25 17:07:29 -0800240
Mike Frysinger68182472014-11-05 22:38:39 -0500241class TestWritePackageIndex(cros_test_lib.MockTestCase, TestPkgIndex):
Alex Klein1699fab2022-09-08 08:46:06 -0600242 """Tests for the WriteToNamedTemporaryFile function."""
David James8c846492011-01-25 17:07:29 -0800243
Alex Klein1699fab2022-09-08 08:46:06 -0600244 def testSimple(self):
245 """Test simple call of WriteToNamedTemporaryFile()"""
246 self.PatchObject(self.pkgindex, "Write")
247 f = self.pkgindex.WriteToNamedTemporaryFile()
248 self.assertEqual(f.read(), "")
David James8c846492011-01-25 17:07:29 -0800249
250
Mike Frysinger36870f92015-04-12 02:59:55 -0400251class TestUploadPrebuilt(cros_test_lib.MockTempDirTestCase):
Alex Klein1699fab2022-09-08 08:46:06 -0600252 """Tests for the _UploadPrebuilt function."""
David James05bcb2b2011-02-09 09:25:47 -0800253
Alex Klein1699fab2022-09-08 08:46:06 -0600254 def setUp(self):
255 class MockTemporaryFile(object):
256 """Mock out the temporary file logic."""
David James05bcb2b2011-02-09 09:25:47 -0800257
Alex Klein1699fab2022-09-08 08:46:06 -0600258 def __init__(self, name):
259 self.name = name
260
261 self.pkgindex = SimplePackageIndex()
262 self.PatchObject(
263 binpkg, "GrabLocalPackageIndex", return_value=self.pkgindex
264 )
265 self.PatchObject(
266 self.pkgindex,
267 "ResolveDuplicateUploads",
268 return_value=PRIVATE_PACKAGES,
269 )
270 self.PatchObject(
271 self.pkgindex,
272 "WriteToNamedTemporaryFile",
273 return_value=MockTemporaryFile("fake"),
274 )
275 self.remote_up_mock = self.PatchObject(prebuilt, "RemoteUpload")
276 self.gs_up_mock = self.PatchObject(prebuilt, "_GsUpload")
277
278 def testSuccessfulGsUpload(self):
279 uploads = {
280 os.path.join(self.tempdir, "private.tbz2"): "gs://foo/private.tbz2"
281 }
282 dev_extras = os.path.join(self.tempdir, "dev-only-extras.tar.xz")
283 osutils.Touch(dev_extras)
284 self.PatchObject(prebuilt, "GenerateUploadDict", return_value=uploads)
285 uploads = uploads.copy()
286 uploads["fake"] = "gs://foo/suffix/Packages"
287 uploads[dev_extras] = "gs://foo/suffix/dev-only-extras.tar.xz"
288 acl = "public-read"
289 uri = self.pkgindex.header["URI"]
290 uploader = prebuilt.PrebuiltUploader(
291 "gs://foo",
292 acl,
293 uri,
294 [],
295 "/",
296 [],
297 False,
298 "foo",
299 False,
300 "x86-foo",
301 [],
302 "",
Bob Haarmanc0082602022-09-20 16:12:43 -0700303 report={},
Alex Klein1699fab2022-09-08 08:46:06 -0600304 )
305 uploader._UploadPrebuilt(self.tempdir, "suffix")
306 self.remote_up_mock.assert_called_once_with(mock.ANY, acl, uploads)
307 self.assertTrue(self.gs_up_mock.called)
David James05bcb2b2011-02-09 09:25:47 -0800308
David James05bcb2b2011-02-09 09:25:47 -0800309
Greg Edelston64620d12023-02-23 15:29:49 -0700310class TestUpdateRemoteSdkLatestFile(cros_test_lib.MockTestCase):
311 """Tests for PrebuiltUploader._UpdateRemoteSdkLatestFile."""
312
313 def setUp(self):
314 self._write_file_patch = self.PatchObject(osutils, "WriteFile")
315 self.PatchObject(prebuilt.PrebuiltUploader, "_Upload")
316 self.PatchObject(
317 gs.GSContext,
318 "LoadKeyValueStore",
319 return_value={
320 "LATEST_SDK": "1000",
321 "LATEST_SDK_UPREV_TARGET": "2000",
322 },
323 )
324 self._uploader = prebuilt.PrebuiltUploader(
325 "gs://foo",
326 "public-read",
327 SimplePackageIndex().header["URI"],
328 [],
329 "/",
330 [],
331 False,
332 "foo",
333 False,
334 "x86-foo",
335 [],
336 "",
337 report={},
338 )
339
340 def testNoChanges(self):
341 self._uploader._UpdateRemoteSdkLatestFile()
342 expected = prebuilt.PrebuiltUploader._CreateRemoteSdkLatestFileContents(
343 "1000", "2000"
344 )
345 self._write_file_patch.assert_called_with(mock.ANY, expected)
346
347 def testChangeLatestSdk(self):
348 self._uploader._UpdateRemoteSdkLatestFile(latest_sdk="3000")
349 expected = prebuilt.PrebuiltUploader._CreateRemoteSdkLatestFileContents(
350 "3000", "2000"
351 )
352 self._write_file_patch.assert_called_with(mock.ANY, expected)
353
354 def testChangeLatestUprevTarget(self):
355 self._uploader._UpdateRemoteSdkLatestFile(
356 latest_sdk_uprev_target="4000"
357 )
358 expected = prebuilt.PrebuiltUploader._CreateRemoteSdkLatestFileContents(
359 "1000", "4000"
360 )
361 self._write_file_patch.assert_called_with(mock.ANY, expected)
362
363 def testChangeBoth(self):
364 self._uploader._UpdateRemoteSdkLatestFile(
365 latest_sdk="3000", latest_sdk_uprev_target="4000"
366 )
367 expected = prebuilt.PrebuiltUploader._CreateRemoteSdkLatestFileContents(
368 "3000", "4000"
369 )
370 self._write_file_patch.assert_called_with(mock.ANY, expected)
371
372
Mike Frysinger36870f92015-04-12 02:59:55 -0400373class TestSyncPrebuilts(cros_test_lib.MockTestCase):
Alex Klein1699fab2022-09-08 08:46:06 -0600374 """Tests for the SyncHostPrebuilts function."""
David James05bcb2b2011-02-09 09:25:47 -0800375
Alex Klein1699fab2022-09-08 08:46:06 -0600376 def setUp(self):
Bob Haarmanc0082602022-09-20 16:12:43 -0700377 clnum = [1]
378
379 def mock_rev(_filename, _data, report, *_args, **_kwargs):
380 report.setdefault("created_cls", []).append(
381 f"https://crrev.com/unittest/{clnum[0]}"
382 )
383 clnum[0] += 1
384
Alex Klein1699fab2022-09-08 08:46:06 -0600385 self.rev_mock = self.PatchObject(
Greg Edelston86aea7b2023-02-15 16:50:25 -0700386 binpkg,
387 "UpdateAndSubmitKeyValueFile",
Bob Haarmanc0082602022-09-20 16:12:43 -0700388 side_effect=mock_rev,
Alex Klein1699fab2022-09-08 08:46:06 -0600389 )
390 self.update_binhost_mock = self.PatchObject(
391 prebuilt, "UpdateBinhostConfFile", return_value=None
392 )
393 self.build_path = "/trunk"
394 self.upload_location = "gs://upload/"
395 self.version = "1"
396 self.binhost = "http://prebuilt/"
397 self.key = "PORTAGE_BINHOST"
398 self.upload_mock = self.PatchObject(
399 prebuilt.PrebuiltUploader, "_UploadPrebuilt", return_value=True
400 )
David James05bcb2b2011-02-09 09:25:47 -0800401
Alex Klein1699fab2022-09-08 08:46:06 -0600402 def _testSyncHostPrebuilts(self, chroot):
403 board = "x86-foo"
404 target = prebuilt.BuildTarget(board, "aura")
405 slave_targets = [prebuilt.BuildTarget("x86-bar", "aura")]
Bob Haarmanc0082602022-09-20 16:12:43 -0700406 report = {}
Alex Klein1699fab2022-09-08 08:46:06 -0600407 if chroot is None:
408 package_path = os.path.join(
409 self.build_path, "chroot", prebuilt._HOST_PACKAGES_PATH
410 )
411 else:
412 package_path = os.path.join(chroot, prebuilt._HOST_PACKAGES_PATH)
413 url_suffix = prebuilt._REL_HOST_PATH % {
414 "version": self.version,
415 "host_arch": prebuilt._HOST_ARCH,
416 "target": target,
417 }
418 packages_url_suffix = "%s/packages" % url_suffix.rstrip("/")
419 url_value = "%s/%s/" % (
420 self.binhost.rstrip("/"),
421 packages_url_suffix.rstrip("/"),
422 )
423 urls = [url_value.replace("foo", "bar"), url_value]
424 binhost = " ".join(urls)
425 uploader = prebuilt.PrebuiltUploader(
426 self.upload_location,
427 "public-read",
428 self.binhost,
429 [],
430 self.build_path,
431 [],
432 False,
433 "foo",
434 False,
435 target,
436 slave_targets,
437 self.version,
Bob Haarmanc0082602022-09-20 16:12:43 -0700438 report,
Alex Klein1699fab2022-09-08 08:46:06 -0600439 chroot=chroot,
440 )
441 uploader.SyncHostPrebuilts(self.key, True, True)
Bob Haarmanc0082602022-09-20 16:12:43 -0700442 self.assertEqual(
443 report,
444 {
445 "created_cls": ["https://crrev.com/unittest/1"],
446 },
447 )
Alex Klein1699fab2022-09-08 08:46:06 -0600448 self.upload_mock.assert_called_once_with(
449 package_path, packages_url_suffix
450 )
451 self.rev_mock.assert_called_once_with(
Bob Haarmanc0082602022-09-20 16:12:43 -0700452 mock.ANY, {self.key: binhost}, report, dryrun=False
Alex Klein1699fab2022-09-08 08:46:06 -0600453 )
454 self.update_binhost_mock.assert_called_once_with(
455 mock.ANY, self.key, binhost
456 )
David James05bcb2b2011-02-09 09:25:47 -0800457
Alex Klein1699fab2022-09-08 08:46:06 -0600458 def testSyncHostPrebuilts(self):
459 self._testSyncHostPrebuilts(chroot=None)
Bob Haarmand1225ea2022-01-19 22:01:42 +0000460
Alex Klein1699fab2022-09-08 08:46:06 -0600461 def testSyncHostPrebuiltsWithChroot(self):
462 self._testSyncHostPrebuilts("/test/chroot")
Bob Haarmand1225ea2022-01-19 22:01:42 +0000463
Alex Klein1699fab2022-09-08 08:46:06 -0600464 def testSyncBoardPrebuilts(self):
465 board = "x86-foo"
466 target = prebuilt.BuildTarget(board, "aura")
467 slave_targets = [prebuilt.BuildTarget("x86-bar", "aura")]
468 board_path = os.path.join(
469 self.build_path, prebuilt._BOARD_PATH % {"board": board}
470 )
471 package_path = os.path.join(board_path, "packages")
472 url_suffix = prebuilt._REL_BOARD_PATH % {
473 "version": self.version,
474 "target": target,
475 }
476 packages_url_suffix = "%s/packages" % url_suffix.rstrip("/")
477 url_value = "%s/%s/" % (
478 self.binhost.rstrip("/"),
479 packages_url_suffix.rstrip("/"),
480 )
481 bar_binhost = url_value.replace("foo", "bar")
482 determine_mock = self.PatchObject(
483 prebuilt, "DeterminePrebuiltConfFile", side_effect=("bar", "foo")
484 )
485 self.PatchObject(prebuilt.PrebuiltUploader, "_UploadSdkTarball")
Bob Haarmanc0082602022-09-20 16:12:43 -0700486 report = {}
Alex Klein1699fab2022-09-08 08:46:06 -0600487 with parallel_unittest.ParallelMock():
488 multiprocessing.Process.exitcode = 0
489 uploader = prebuilt.PrebuiltUploader(
490 self.upload_location,
491 "public-read",
492 self.binhost,
493 [],
494 self.build_path,
495 [],
496 False,
497 "foo",
498 False,
499 target,
500 slave_targets,
501 self.version,
Bob Haarmanc0082602022-09-20 16:12:43 -0700502 report,
Alex Klein1699fab2022-09-08 08:46:06 -0600503 )
504 uploader.SyncBoardPrebuilts(
Greg Edelston8da51ce2023-03-22 10:40:59 -0600505 self.key, True, True, True, None, None, None, None, None, True
Alex Klein1699fab2022-09-08 08:46:06 -0600506 )
507 determine_mock.assert_has_calls(
508 [
509 mock.call(self.build_path, slave_targets[0]),
510 mock.call(self.build_path, target),
511 ]
512 )
513 self.upload_mock.assert_called_once_with(
514 package_path, packages_url_suffix
515 )
516 self.rev_mock.assert_has_calls(
517 [
Bob Haarmanc0082602022-09-20 16:12:43 -0700518 mock.call(
519 "bar",
520 {self.key: bar_binhost},
521 {
522 "created_cls": [
523 "https://crrev.com/unittest/1",
524 "https://crrev.com/unittest/2",
525 ],
526 },
527 dryrun=False,
528 ),
529 mock.call(
530 "foo",
531 {self.key: url_value},
532 {
533 "created_cls": [
534 "https://crrev.com/unittest/1",
535 "https://crrev.com/unittest/2",
536 ],
537 },
538 dryrun=False,
539 ),
Alex Klein1699fab2022-09-08 08:46:06 -0600540 ]
541 )
542 self.update_binhost_mock.assert_has_calls(
543 [
544 mock.call(mock.ANY, self.key, bar_binhost),
545 mock.call(mock.ANY, self.key, url_value),
546 ]
547 )
David James05bcb2b2011-02-09 09:25:47 -0800548
549
Mike Frysinger36870f92015-04-12 02:59:55 -0400550class TestMain(cros_test_lib.MockTestCase):
Alex Klein1699fab2022-09-08 08:46:06 -0600551 """Tests for the main() function."""
David Jamesc0f158a2011-02-22 16:07:29 -0800552
Alex Klein1699fab2022-09-08 08:46:06 -0600553 def testMain(self):
554 """Test that the main function works."""
Bob Haarman35460c22022-11-08 00:11:59 +0000555 # Use a real object as returned from ParseOptions as a spec for
556 # the mock options object, so that we don't have any properties
557 # that the real object doesn't have.
558 options_spec, _ = prebuilt.ParseOptions(
559 [
560 "--dry-run",
561 "--build-path",
562 "/trunk",
563 "-u",
564 "gs://upload",
565 ]
566 )
567 options = mock.MagicMock(spec=options_spec)
Alex Klein1699fab2022-09-08 08:46:06 -0600568 old_binhost = "http://prebuilt/1"
569 options.previous_binhost_url = [old_binhost]
570 options.board = "x86-foo"
571 options.profile = None
572 target = prebuilt.BuildTarget(options.board, options.profile)
573 options.build_path = "/trunk"
574 options.chroot = None
575 options.dryrun = False
576 options.private = True
577 options.packages = []
578 options.sync_host = True
579 options.git_sync = True
Greg Edelston8da51ce2023-03-22 10:40:59 -0600580 options.sync_remote_latest_sdk_file = True
Alex Klein1699fab2022-09-08 08:46:06 -0600581 options.upload_board_tarball = True
582 options.prepackaged_tarball = None
583 options.toolchains_overlay_tarballs = []
584 options.toolchains_overlay_upload_path = ""
585 options.toolchain_tarballs = []
586 options.toolchain_upload_path = ""
587 options.upload = "gs://upload/"
588 options.binhost_base_url = options.upload
589 options.prepend_version = True
590 options.set_version = None
591 options.skip_upload = False
592 options.filters = True
593 options.key = "PORTAGE_BINHOST"
594 options.binhost_conf_dir = None
595 options.sync_binhost_conf = True
596 options.slave_targets = [prebuilt.BuildTarget("x86-bar", "aura")]
597 self.PatchObject(
598 prebuilt, "ParseOptions", return_value=tuple([options, target])
599 )
600 self.PatchObject(binpkg, "GrabRemotePackageIndex", return_value=True)
601 init_mock = self.PatchObject(
602 prebuilt.PrebuiltUploader, "__init__", return_value=None
603 )
604 expected_gs_acl_path = os.path.join(
605 "/fake_path", prebuilt._GOOGLESTORAGE_GSUTIL_FILE
606 )
607 self.PatchObject(
608 portage_util, "FindOverlayFile", return_value=expected_gs_acl_path
609 )
610 host_mock = self.PatchObject(
611 prebuilt.PrebuiltUploader, "SyncHostPrebuilts", return_value=None
612 )
613 board_mock = self.PatchObject(
614 prebuilt.PrebuiltUploader, "SyncBoardPrebuilts", return_value=None
615 )
Mike Frysinger36870f92015-04-12 02:59:55 -0400616
Alex Klein1699fab2022-09-08 08:46:06 -0600617 prebuilt.main([])
Mike Frysinger36870f92015-04-12 02:59:55 -0400618
Alex Klein1699fab2022-09-08 08:46:06 -0600619 init_mock.assert_called_once_with(
620 options.upload,
621 expected_gs_acl_path,
622 options.upload,
623 mock.ANY,
624 options.build_path,
625 options.packages,
626 False,
627 None,
628 False,
629 target,
630 options.slave_targets,
631 mock.ANY,
Bob Haarmanc0082602022-09-20 16:12:43 -0700632 {},
Alex Klein1699fab2022-09-08 08:46:06 -0600633 None,
634 )
635 board_mock.assert_called_once_with(
636 options.key,
637 options.git_sync,
638 options.sync_binhost_conf,
639 options.upload_board_tarball,
640 None,
641 [],
642 "",
643 [],
644 "",
Greg Edelston8da51ce2023-03-22 10:40:59 -0600645 options.sync_remote_latest_sdk_file,
Alex Klein1699fab2022-09-08 08:46:06 -0600646 )
647 host_mock.assert_called_once_with(
648 options.key, options.git_sync, options.sync_binhost_conf
649 )
David Jamesc0f158a2011-02-22 16:07:29 -0800650
Mike Frysinger9e979b92012-11-29 02:55:09 -0500651
Mike Frysinger68182472014-11-05 22:38:39 -0500652class TestSdk(cros_test_lib.MockTestCase):
Alex Klein1699fab2022-09-08 08:46:06 -0600653 """Test logic related to uploading SDK binaries"""
Mike Frysinger9e979b92012-11-29 02:55:09 -0500654
Alex Klein1699fab2022-09-08 08:46:06 -0600655 def setUp(self):
656 self.PatchObject(
657 prebuilt,
658 "_GsUpload",
659 side_effect=Exception("should not get called"),
660 )
661 self.PatchObject(
662 prebuilt,
663 "UpdateBinhostConfFile",
664 side_effect=Exception("should not get called"),
665 )
Greg Edelston64620d12023-02-23 15:29:49 -0700666 self.PatchObject(
667 gs.GSContext,
668 "LoadKeyValueStore",
669 return_value={
670 "LATEST_SDK": "1000",
671 "LATEST_SDK_UPREV_TARGET": "2000",
672 },
673 )
Greg Edelstonf3916f92023-02-22 15:49:38 -0700674 self.write_file_mock = self.PatchObject(osutils, "WriteFile")
Alex Klein1699fab2022-09-08 08:46:06 -0600675 self.upload_mock = self.PatchObject(
676 prebuilt.PrebuiltUploader, "_Upload"
677 )
Mike Frysinger9e979b92012-11-29 02:55:09 -0500678
Alex Klein1699fab2022-09-08 08:46:06 -0600679 self.acl = "magic-acl"
Mike Frysinger9e979b92012-11-29 02:55:09 -0500680
Alex Klein1699fab2022-09-08 08:46:06 -0600681 # All these args pretty much get ignored. Whee.
682 self.uploader = prebuilt.PrebuiltUploader(
683 "gs://foo",
684 self.acl,
685 "prebuilt",
686 [],
687 "/",
688 [],
689 False,
690 "foo",
691 False,
692 "x86-foo",
693 [],
694 "chroot-1234",
Bob Haarmanc0082602022-09-20 16:12:43 -0700695 report={},
Alex Klein1699fab2022-09-08 08:46:06 -0600696 )
Mike Frysinger9e979b92012-11-29 02:55:09 -0500697
Alex Klein1699fab2022-09-08 08:46:06 -0600698 def testSdkUpload(
699 self,
700 to_tarballs=(),
701 to_upload_path=None,
702 tc_tarballs=(),
703 tc_upload_path=None,
704 ):
705 """Make sure we can upload just an SDK tarball"""
706 tar = "sdk.tar.xz"
707 ver = "1234"
708 vtar = "cros-sdk-%s.tar.xz" % ver
Mike Frysinger9e979b92012-11-29 02:55:09 -0500709
Greg Edelstonf3916f92023-02-22 15:49:38 -0700710 upload_calls = [
Alex Klein1699fab2022-09-08 08:46:06 -0600711 mock.call(
712 "%s.Manifest" % tar, "gs://chromiumos-sdk/%s.Manifest" % vtar
713 ),
714 mock.call(tar, "gs://chromiumos-sdk/%s" % vtar),
715 ]
716 for to in to_tarballs:
717 to = to.split(":")
Greg Edelstonf3916f92023-02-22 15:49:38 -0700718 upload_calls.append(
Alex Klein1699fab2022-09-08 08:46:06 -0600719 mock.call(
720 to[1],
721 ("gs://chromiumos-sdk/" + to_upload_path)
722 % {"toolchains": to[0]},
723 )
724 )
725 for tc in tc_tarballs:
726 tc = tc.split(":")
Greg Edelstonf3916f92023-02-22 15:49:38 -0700727 upload_calls.append(
Alex Klein1699fab2022-09-08 08:46:06 -0600728 mock.call(
729 tc[1],
730 ("gs://chromiumos-sdk/" + tc_upload_path)
731 % {"target": tc[0]},
732 )
733 )
Greg Edelstonf3916f92023-02-22 15:49:38 -0700734 upload_calls.append(
Alex Klein1699fab2022-09-08 08:46:06 -0600735 mock.call(mock.ANY, "gs://chromiumos-sdk/cros-sdk-latest.conf")
736 )
Mike Frysinger9e979b92012-11-29 02:55:09 -0500737
Alex Klein1699fab2022-09-08 08:46:06 -0600738 self.uploader._UploadSdkTarball(
739 "amd64-host",
740 "",
741 tar,
742 to_tarballs,
743 to_upload_path,
744 tc_tarballs,
745 tc_upload_path,
Greg Edelston8da51ce2023-03-22 10:40:59 -0600746 True,
Alex Klein1699fab2022-09-08 08:46:06 -0600747 )
Greg Edelstonf3916f92023-02-22 15:49:38 -0700748 self.upload_mock.assert_has_calls(upload_calls)
749
750 expected_latest_file_contents = f"""\
751# The most recent SDK that is tested and ready for use.
752LATEST_SDK="{ver}"
753
754# The most recently built version. New uprev attempts should target this.
755# Warning: This version may not be tested yet.
Greg Edelston64620d12023-02-23 15:29:49 -0700756LATEST_SDK_UPREV_TARGET=\"2000\""""
Greg Edelstonf3916f92023-02-22 15:49:38 -0700757 self.write_file_mock.assert_any_call(
758 mock.ANY, expected_latest_file_contents
759 )
Mike Frysinger9e979b92012-11-29 02:55:09 -0500760
Alex Klein1699fab2022-09-08 08:46:06 -0600761 def testBoardOverlayTarballUpload(self):
762 """Make sure processing of board-specific overlay tarballs works."""
763 to_tarballs = (
764 (
765 "i686-pc-linux-gnu:"
766 "/some/path/built-sdk-overlay-toolchains-i686-pc-linux-gnu.tar.xz"
767 ),
768 (
769 "armv7a-cros-linux-gnueabi-arm-none-eabi:"
770 "/some/path/built-sdk-overlay-toolchains-armv7a-cros-linux-gnueabi-"
771 "arm-none-eabi"
772 ),
773 )
774 to_upload_path = "1994/04/cros-sdk-overlay-toolchains-%(toolchains)s-1994.04.02.tar.xz"
775 self.testSdkUpload(
776 to_tarballs=to_tarballs, to_upload_path=to_upload_path
777 )
Gilad Arnoldad333182015-05-27 15:50:41 -0700778
Alex Klein1699fab2022-09-08 08:46:06 -0600779 def testToolchainTarballUpload(self):
780 """Make sure processing of toolchain tarballs works."""
781 tc_tarballs = (
782 "i686:/some/i686.tar.xz",
783 "arm-none:/some/arm.tar.xz",
784 )
785 tc_upload_path = "1994/04/%(target)s-1994.04.02.tar.xz"
786 self.testSdkUpload(
787 tc_tarballs=tc_tarballs, tc_upload_path=tc_upload_path
788 )