blob: a4f096c9ba0f7ee2ab11259e9d2cd9e5e1ac52cc [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(
505 self.key, True, True, True, None, None, None, None, None
506 )
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
580 options.upload_board_tarball = True
581 options.prepackaged_tarball = None
582 options.toolchains_overlay_tarballs = []
583 options.toolchains_overlay_upload_path = ""
584 options.toolchain_tarballs = []
585 options.toolchain_upload_path = ""
586 options.upload = "gs://upload/"
587 options.binhost_base_url = options.upload
588 options.prepend_version = True
589 options.set_version = None
590 options.skip_upload = False
591 options.filters = True
592 options.key = "PORTAGE_BINHOST"
593 options.binhost_conf_dir = None
594 options.sync_binhost_conf = True
595 options.slave_targets = [prebuilt.BuildTarget("x86-bar", "aura")]
596 self.PatchObject(
597 prebuilt, "ParseOptions", return_value=tuple([options, target])
598 )
599 self.PatchObject(binpkg, "GrabRemotePackageIndex", return_value=True)
600 init_mock = self.PatchObject(
601 prebuilt.PrebuiltUploader, "__init__", return_value=None
602 )
603 expected_gs_acl_path = os.path.join(
604 "/fake_path", prebuilt._GOOGLESTORAGE_GSUTIL_FILE
605 )
606 self.PatchObject(
607 portage_util, "FindOverlayFile", return_value=expected_gs_acl_path
608 )
609 host_mock = self.PatchObject(
610 prebuilt.PrebuiltUploader, "SyncHostPrebuilts", return_value=None
611 )
612 board_mock = self.PatchObject(
613 prebuilt.PrebuiltUploader, "SyncBoardPrebuilts", return_value=None
614 )
Mike Frysinger36870f92015-04-12 02:59:55 -0400615
Alex Klein1699fab2022-09-08 08:46:06 -0600616 prebuilt.main([])
Mike Frysinger36870f92015-04-12 02:59:55 -0400617
Alex Klein1699fab2022-09-08 08:46:06 -0600618 init_mock.assert_called_once_with(
619 options.upload,
620 expected_gs_acl_path,
621 options.upload,
622 mock.ANY,
623 options.build_path,
624 options.packages,
625 False,
626 None,
627 False,
628 target,
629 options.slave_targets,
630 mock.ANY,
Bob Haarmanc0082602022-09-20 16:12:43 -0700631 {},
Alex Klein1699fab2022-09-08 08:46:06 -0600632 None,
633 )
634 board_mock.assert_called_once_with(
635 options.key,
636 options.git_sync,
637 options.sync_binhost_conf,
638 options.upload_board_tarball,
639 None,
640 [],
641 "",
642 [],
643 "",
644 )
645 host_mock.assert_called_once_with(
646 options.key, options.git_sync, options.sync_binhost_conf
647 )
David Jamesc0f158a2011-02-22 16:07:29 -0800648
Mike Frysinger9e979b92012-11-29 02:55:09 -0500649
Mike Frysinger68182472014-11-05 22:38:39 -0500650class TestSdk(cros_test_lib.MockTestCase):
Alex Klein1699fab2022-09-08 08:46:06 -0600651 """Test logic related to uploading SDK binaries"""
Mike Frysinger9e979b92012-11-29 02:55:09 -0500652
Alex Klein1699fab2022-09-08 08:46:06 -0600653 def setUp(self):
654 self.PatchObject(
655 prebuilt,
656 "_GsUpload",
657 side_effect=Exception("should not get called"),
658 )
659 self.PatchObject(
660 prebuilt,
661 "UpdateBinhostConfFile",
662 side_effect=Exception("should not get called"),
663 )
Greg Edelston64620d12023-02-23 15:29:49 -0700664 self.PatchObject(
665 gs.GSContext,
666 "LoadKeyValueStore",
667 return_value={
668 "LATEST_SDK": "1000",
669 "LATEST_SDK_UPREV_TARGET": "2000",
670 },
671 )
Greg Edelstonf3916f92023-02-22 15:49:38 -0700672 self.write_file_mock = self.PatchObject(osutils, "WriteFile")
Alex Klein1699fab2022-09-08 08:46:06 -0600673 self.upload_mock = self.PatchObject(
674 prebuilt.PrebuiltUploader, "_Upload"
675 )
Mike Frysinger9e979b92012-11-29 02:55:09 -0500676
Alex Klein1699fab2022-09-08 08:46:06 -0600677 self.acl = "magic-acl"
Mike Frysinger9e979b92012-11-29 02:55:09 -0500678
Alex Klein1699fab2022-09-08 08:46:06 -0600679 # All these args pretty much get ignored. Whee.
680 self.uploader = prebuilt.PrebuiltUploader(
681 "gs://foo",
682 self.acl,
683 "prebuilt",
684 [],
685 "/",
686 [],
687 False,
688 "foo",
689 False,
690 "x86-foo",
691 [],
692 "chroot-1234",
Bob Haarmanc0082602022-09-20 16:12:43 -0700693 report={},
Alex Klein1699fab2022-09-08 08:46:06 -0600694 )
Mike Frysinger9e979b92012-11-29 02:55:09 -0500695
Alex Klein1699fab2022-09-08 08:46:06 -0600696 def testSdkUpload(
697 self,
698 to_tarballs=(),
699 to_upload_path=None,
700 tc_tarballs=(),
701 tc_upload_path=None,
702 ):
703 """Make sure we can upload just an SDK tarball"""
704 tar = "sdk.tar.xz"
705 ver = "1234"
706 vtar = "cros-sdk-%s.tar.xz" % ver
Mike Frysinger9e979b92012-11-29 02:55:09 -0500707
Greg Edelstonf3916f92023-02-22 15:49:38 -0700708 upload_calls = [
Alex Klein1699fab2022-09-08 08:46:06 -0600709 mock.call(
710 "%s.Manifest" % tar, "gs://chromiumos-sdk/%s.Manifest" % vtar
711 ),
712 mock.call(tar, "gs://chromiumos-sdk/%s" % vtar),
713 ]
714 for to in to_tarballs:
715 to = to.split(":")
Greg Edelstonf3916f92023-02-22 15:49:38 -0700716 upload_calls.append(
Alex Klein1699fab2022-09-08 08:46:06 -0600717 mock.call(
718 to[1],
719 ("gs://chromiumos-sdk/" + to_upload_path)
720 % {"toolchains": to[0]},
721 )
722 )
723 for tc in tc_tarballs:
724 tc = tc.split(":")
Greg Edelstonf3916f92023-02-22 15:49:38 -0700725 upload_calls.append(
Alex Klein1699fab2022-09-08 08:46:06 -0600726 mock.call(
727 tc[1],
728 ("gs://chromiumos-sdk/" + tc_upload_path)
729 % {"target": tc[0]},
730 )
731 )
Greg Edelstonf3916f92023-02-22 15:49:38 -0700732 upload_calls.append(
Alex Klein1699fab2022-09-08 08:46:06 -0600733 mock.call(mock.ANY, "gs://chromiumos-sdk/cros-sdk-latest.conf")
734 )
Mike Frysinger9e979b92012-11-29 02:55:09 -0500735
Alex Klein1699fab2022-09-08 08:46:06 -0600736 self.uploader._UploadSdkTarball(
737 "amd64-host",
738 "",
739 tar,
740 to_tarballs,
741 to_upload_path,
742 tc_tarballs,
743 tc_upload_path,
744 )
Greg Edelstonf3916f92023-02-22 15:49:38 -0700745 self.upload_mock.assert_has_calls(upload_calls)
746
747 expected_latest_file_contents = f"""\
748# The most recent SDK that is tested and ready for use.
749LATEST_SDK="{ver}"
750
751# The most recently built version. New uprev attempts should target this.
752# Warning: This version may not be tested yet.
Greg Edelston64620d12023-02-23 15:29:49 -0700753LATEST_SDK_UPREV_TARGET=\"2000\""""
Greg Edelstonf3916f92023-02-22 15:49:38 -0700754 self.write_file_mock.assert_any_call(
755 mock.ANY, expected_latest_file_contents
756 )
Mike Frysinger9e979b92012-11-29 02:55:09 -0500757
Alex Klein1699fab2022-09-08 08:46:06 -0600758 def testBoardOverlayTarballUpload(self):
759 """Make sure processing of board-specific overlay tarballs works."""
760 to_tarballs = (
761 (
762 "i686-pc-linux-gnu:"
763 "/some/path/built-sdk-overlay-toolchains-i686-pc-linux-gnu.tar.xz"
764 ),
765 (
766 "armv7a-cros-linux-gnueabi-arm-none-eabi:"
767 "/some/path/built-sdk-overlay-toolchains-armv7a-cros-linux-gnueabi-"
768 "arm-none-eabi"
769 ),
770 )
771 to_upload_path = "1994/04/cros-sdk-overlay-toolchains-%(toolchains)s-1994.04.02.tar.xz"
772 self.testSdkUpload(
773 to_tarballs=to_tarballs, to_upload_path=to_upload_path
774 )
Gilad Arnoldad333182015-05-27 15:50:41 -0700775
Alex Klein1699fab2022-09-08 08:46:06 -0600776 def testToolchainTarballUpload(self):
777 """Make sure processing of toolchain tarballs works."""
778 tc_tarballs = (
779 "i686:/some/i686.tar.xz",
780 "arm-none:/some/arm.tar.xz",
781 )
782 tc_upload_path = "1994/04/%(target)s-1994.04.02.tar.xz"
783 self.testSdkUpload(
784 tc_tarballs=tc_tarballs, tc_upload_path=tc_upload_path
785 )