blob: 353f6b6e7d86d34b878da538a3c65998686756ed [file] [log] [blame]
# Copyright 2012 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Unit tests for the deploy_chrome script."""
import datetime
from unittest import mock
from chromite.contrib import purge_builds
from chromite.lib import cros_test_lib
from chromite.lib import gs
from chromite.lib import gs_unittest
# pylint: disable=protected-access
class TestHelperMethods(cros_test_lib.TestCase):
"""Main tests."""
def testKnownCases(self):
"""The stats upload path."""
CASES = (
("cros/factory-veyron-7505.B", "7505"),
("origin/factory-2723.14.B", "2723.14"),
("remote/firmware-falco_peppy-4389.B", "4389"),
("factory-veyron-7505.B", "7505"),
("factory-2723.14.B", "2723.14"),
("firmware-falco_peppy-4389.B", "4389"),
)
for branch, expected in CASES:
self.assertEqual(purge_builds.ParseBranchName(branch), expected)
def testListRemoteBranches(self):
branches = purge_builds.ListRemoteBranches()
# We know there are more than 300 remote branches for chromite.
self.assertGreater(len(branches), 300)
def testProtectedBranchVersions(self):
branch_names = [
"cros/factory-veyron-7505.B",
"origin/factory-2723.14.B",
"remote/firmware-falco_peppy-4389.B",
]
branch_versions = purge_builds.ProtectedBranchVersions(branch_names)
# We know there are more than 100 firmware/factory branches.
self.assertEqual(branch_versions, ["7505", "2723.14", "4389"])
def testProtectedBranchVersionsLive(self):
branches = purge_builds.ListRemoteBranches()
branch_versions = purge_builds.ProtectedBranchVersions(branches)
# We know there are more than 100 firmware/factory branches.
self.assertGreater(len(branch_versions), 100)
# cros/firmware-snow-2695.90.B is a known branch. Ensure it's listed.
self.assertIn("2695.90", branch_versions)
def testParseChromeosReleasesBuildUri(self):
"""Test parseChromeosReleasesBuildUri."""
self.assertEqual(
purge_builds.ParseChromeosReleasesBuildUri(
"gs://chromeos-releases/canary-channel/duck/6652.0.0/"
),
"6652.0.0",
)
def testVersionBranchMatch(self):
"""Test versionBranchMatch."""
self.assertTrue(purge_builds.VersionBranchMatch("1.2.3", "1"))
self.assertTrue(purge_builds.VersionBranchMatch("1.2.3", "1.2"))
self.assertTrue(purge_builds.VersionBranchMatch("1.2.357", "1.2"))
self.assertFalse(purge_builds.VersionBranchMatch("12.24.37", "1.2"))
self.assertFalse(purge_builds.VersionBranchMatch("1.0.0", "1"))
self.assertFalse(purge_builds.VersionBranchMatch("1.2.0", "1.2"))
def testInBranches(self):
"""Test versionBranchMatch."""
branches = ("1", "2.2", "5.3")
self.assertTrue(purge_builds.InBranches("1.2.3", branches))
self.assertTrue(purge_builds.InBranches("1.2.3", branches))
self.assertTrue(purge_builds.InBranches("1.2.357", branches))
self.assertTrue(purge_builds.InBranches("5.3.23", branches))
self.assertFalse(purge_builds.InBranches("12.24.37", branches))
self.assertFalse(purge_builds.InBranches("1.0.0", branches))
self.assertFalse(purge_builds.InBranches("2.1.0", branches))
self.assertFalse(purge_builds.InBranches("5.3.0", branches))
class TestBucketSearches(gs_unittest.AbstractGSContextTest):
"""Test GS interactions in purge_builds."""
def setUp(self):
self.expireDate = datetime.datetime.now()
self.preExpire = self.expireDate + datetime.timedelta(minutes=5)
self.postExpire = self.expireDate - datetime.timedelta(minutes=5)
self.file_no_timestamp = gs.GSListResult(
"gs://chromeos-releases/canary-channel/plain_file",
None,
None,
None,
None,
)
self.file_with_timestamp = self.mockResult(
"gs://chromeos-releases/canary-channel/plain_file"
)
self.directory = self.mockResult(
"gs://chromeos-releases/canary-channel/x86-alex/1.2.3/"
)
def mockResult(self, url, expired=True):
if url.endswith("/"):
creation_time = None
else:
creation_time = self.postExpire if expired else self.preExpire
return gs.GSListResult(
content_length=0,
creation_time=creation_time,
url=url,
generation=0,
metageneration=0,
)
def patchSafeList(self):
listResults = {
"gs://chromeos-image-archive/": [
self.mockResult("gs://chromeos-image-archive/foo-paladin/"),
self.mockResult(
"gs://chromeos-image-archive/trybot-foo-paladin/"
),
self.mockResult("gs://chromeos-image-archive/foo-factory/"),
self.mockResult(
"gs://chromeos-image-archive/trybot-foo-factory/"
),
self.mockResult("gs://chromeos-image-archive/foo-firmware/"),
self.mockResult(
"gs://chromeos-image-archive/trybot-foo-firmware/"
),
self.mockResult("gs://chromeos-image-archive/bar-firmware/"),
self.mockResult(
"gs://chromeos-image-archive/trybot-whirlwind-test-ap/"
),
self.mockResult(
"gs://chromeos-image-archive/trybot-stumpy-test-ap/"
),
self.mockResult(
"gs://chromeos-image-archive/trybot-whirlwind-test-ap-tryjob/"
),
self.mockResult(
"gs://chromeos-image-archive/gale-test-ap-tryjob/"
),
],
"gs://chromeos-image-archive/foo-paladin/": [
self.mockResult(
"gs://chromeos-image-archive/foo-paladin/plain_file"
),
self.mockResult(
"gs://chromeos-image-archive/foo-paladin/1.2.3/"
),
],
"gs://chromeos-image-archive/foo-paladin/1.2.3/**": [
self.mockResult(
"gs://chromeos-image-archive/foo-paladin/1.2.3/a"
),
self.mockResult(
"gs://chromeos-image-archive/foo-paladin/1.2.3/b"
),
self.mockResult(
"gs://chromeos-image-archive/foo-paladin/1.2.3/nested/c"
),
],
"gs://chromeos-image-archive/trybot-foo-paladin/": [],
"gs://chromeos-image-archive/foo-factory/": [],
"gs://chromeos-image-archive/trybot-foo-factory/": [],
"gs://chromeos-image-archive/trybot-foo-firmware/": [],
"gs://chromeos-releases/": [
self.mockResult("gs://chromeos-releases/stable-channel/"),
self.mockResult("gs://chromeos-releases/beta-channel/"),
self.mockResult("gs://chromeos-releases/dev-channel/"),
self.mockResult("gs://chromeos-releases/canary-channel/"),
self.mockResult("gs://chromeos-releases/logs/"),
self.mockResult("gs://chromeos-releases/top-level-file"),
],
"gs://chromeos-releases/canary-channel/": [
self.mockResult(
"gs://chromeos-releases/canary-channel/arkham/"
),
self.mockResult(
"gs://chromeos-releases/canary-channel/plain_file"
),
self.mockResult(
"gs://chromeos-releases/canary-channel/x86-alex/"
),
],
"gs://chromeos-releases/canary-channel/plain_file": [
self.mockResult(
"gs://chromeos-releases/canary-channel/plain_file"
),
],
"gs://chromeos-releases/canary-channel/arkham/": [
self.mockResult(
"gs://chromeos-releases/canary-channel/arkham/6301.0.0/"
),
self.mockResult(
"gs://chromeos-releases/canary-channel/arkham/6301.1.0/"
),
self.mockResult(
"gs://chromeos-releases/canary-channel/arkham/7023.0.0/"
),
self.mockResult(
"gs://chromeos-releases/canary-channel/arkham/noparse/"
),
],
"gs://chromeos-releases/canary-channel/arkham/6301.0.0/**": [
self.mockResult(
"gs://chromeos-releases/canary-channel/arkham/6301.0.0/a"
),
self.mockResult(
"gs://chromeos-releases/canary-channel/arkham/6301.0.0/b"
),
],
"gs://chromeos-releases/canary-channel/arkham/7023.0.0/**": [
self.mockResult(
"gs://chromeos-releases/canary-channel/arkham/7023.0.0/a"
),
self.mockResult(
"gs://chromeos-releases/canary-channel/arkham/7023.0.0/b"
),
],
"gs://chromeos-releases/canary-channel/arkham/noparse/**": [
self.mockResult(
"gs://chromeos-releases/canary-channel/arkham/noparse/a"
),
self.mockResult(
"gs://chromeos-releases/canary-channel/arkham/noparse/b"
),
],
"gs://chromeos-releases/canary-channel/x86-alex/": [
self.mockResult(
"gs://chromeos-releases/canary-channel/x86-alex/1.2.3/"
),
self.mockResult(
"gs://chromeos-releases/canary-channel/x86-alex/1.2.4/"
),
],
"gs://chromeos-releases/canary-channel/x86-alex/1.2.3/**": [
self.mockResult(
"gs://chromeos-releases/canary-channel/x86-alex/1.2.3/a"
),
self.mockResult(
"gs://chromeos-releases/canary-channel/x86-alex/1.2.3/b",
expired=False,
),
self.mockResult(
"gs://chromeos-releases/canary-channel/x86-alex/1.2.3/"
"nest/deep"
),
],
"gs://chromeos-releases/canary-channel/x86-alex/1.2.4/**": [
self.mockResult(
"gs://chromeos-releases/canary-channel/x86-alex/1.2.4/a"
),
self.mockResult(
"gs://chromeos-releases/canary-channel/x86-alex/1.2.4/b"
),
],
}
self.PatchObject(
purge_builds,
"SafeList",
side_effect=lambda _, url: listResults[url],
)
def testLocateChromeosReleasesProtectedPrefixes(self):
"""Test locateChromeosReleasesProtectedPrefixes."""
protected_versions = ("6301", "7000.2")
self.patchSafeList()
result = purge_builds.LocateChromeosReleasesProtectedPrefixes(
self.ctx, protected_versions
)
self.assertEqual(
result,
[
"gs://chromeos-releases/Attic",
"gs://chromeos-releases/stable-channel",
"gs://chromeos-releases/beta-channel",
"gs://chromeos-releases/dev-channel",
"gs://chromeos-releases/logs",
"gs://chromeos-releases/tobesigned",
"gs://chromeos-releases/canary-channel/arkham/6301.1.0/",
],
)
def testLocateChromeosImageArchiveProtectedPrefixes(self):
self.patchSafeList()
result = purge_builds.LocateChromeosImageArchiveProtectedPrefixes(
self.ctx
)
self.assertEqual(
result,
[
"gs://chromeos-image-archive/foo-firmware/",
"gs://chromeos-image-archive/bar-firmware/",
"gs://chromeos-image-archive/trybot-whirlwind-test-ap/",
"gs://chromeos-image-archive/trybot-stumpy-test-ap/",
"gs://chromeos-image-archive/trybot-whirlwind-test-ap-tryjob/",
"gs://chromeos-image-archive/gale-test-ap-tryjob/",
],
)
def testProduceFilteredCandidatesArchive(self):
protected_prefixes = (
"gs://chromeos-image-archive/foo-firmware",
"gs://chromeos-image-archive/bar-firmware",
"gs://chromeos-image-archive/trybot-whirlwind-test-ap/",
"gs://chromeos-image-archive/trybot-stumpy-test-ap/",
"gs://chromeos-image-archive/trybot-whirlwind-test-ap-tryjob/",
"gs://chromeos-image-archive/gale-test-ap-tryjob/",
)
self.patchSafeList()
result = purge_builds.ProduceFilteredCandidates(
self.ctx, "gs://chromeos-image-archive/", protected_prefixes, 2
)
self.assertEqual(
list(result),
[
self.mockResult(
"gs://chromeos-image-archive/foo-paladin/plain_file"
),
self.mockResult(
"gs://chromeos-image-archive/foo-paladin/1.2.3/"
),
],
)
def testProduceFilteredCandidatesReleases(self):
protected_prefixes = (
"gs://chromeos-releases/Attic",
"gs://chromeos-releases/stable-channel",
"gs://chromeos-releases/beta-channel",
"gs://chromeos-releases/dev-channel",
"gs://chromeos-releases/logs",
"gs://chromeos-releases/tobesigned",
"gs://chromeos-releases/canary-channel/arkham/6301.1.0/",
"gs://chromeos-releases/canary-channel/auron/6301.18.0/",
)
self.patchSafeList()
result = purge_builds.ProduceFilteredCandidates(
self.ctx, "gs://chromeos-releases/", protected_prefixes, 3
)
self.assertEqual(
list(result),
[
self.mockResult(
"gs://chromeos-releases/canary-channel/arkham/6301.0.0/"
),
self.mockResult(
"gs://chromeos-releases/canary-channel/arkham/7023.0.0/"
),
self.mockResult(
"gs://chromeos-releases/canary-channel/arkham/noparse/"
),
self.mockResult(
"gs://chromeos-releases/canary-channel/plain_file"
),
self.mockResult(
"gs://chromeos-releases/canary-channel/x86-alex/1.2.3/"
),
self.mockResult(
"gs://chromeos-releases/canary-channel/x86-alex/1.2.4/"
),
self.mockResult("gs://chromeos-releases/top-level-file"),
],
)
def testExpand(self):
self.patchSafeList()
result = purge_builds.Expand(self.ctx, self.file_no_timestamp)
self.assertEqual(result, [self.file_with_timestamp])
result = purge_builds.Expand(self.ctx, self.file_with_timestamp)
self.assertEqual(result, [self.file_with_timestamp])
result = purge_builds.Expand(self.ctx, self.directory)
self.assertEqual(
result,
[
self.mockResult(
"gs://chromeos-releases/canary-channel/x86-alex/1.2.3/a"
),
self.mockResult(
"gs://chromeos-releases/canary-channel/x86-alex/1.2.3/b",
expired=False,
),
self.mockResult(
"gs://chromeos-releases/canary-channel/x86-alex/1.2.3/nest/deep"
),
],
)
def testExpire(self):
# Dryrun, move nothing.
purge_builds.Expire(self.ctx, dryrun=True, url="gs://foo/bar")
purge_builds.Expire(
self.ctx, dryrun=True, url="gs://chromeos-releases/deep/nested/file"
)
self.assertEqual(self.gs_mock.call_args_list, [])
# Really move stuff.
purge_builds.Expire(self.ctx, dryrun=False, url="gs://foo/bar")
purge_builds.Expire(
self.ctx,
dryrun=False,
url="gs://chromeos-releases/deep/nested/file",
)
self.assertEqual(
self.gs_mock.call_args_list,
[
mock.call(
self.ctx,
[
"mv",
"--",
"gs://foo/bar",
"gs://foo-backup/bar",
],
),
mock.call(
self.ctx,
[
"mv",
"--",
"gs://chromeos-releases/deep/nested/file",
"gs://chromeos-releases-backup/deep/nested/file",
],
),
],
)
def testExpireAndExpandDryrun(self):
self.patchSafeList()
purge_builds.ExpandAndExpire(
self.ctx, True, self.expireDate, self.file_no_timestamp
)
purge_builds.ExpandAndExpire(
self.ctx, True, self.expireDate, self.file_with_timestamp
)
purge_builds.ExpandAndExpire(
self.ctx, True, self.expireDate, self.directory
)
self.assertEqual(self.gs_mock.call_args_list, [])
def testExpireAndExpandNoTimestamp(self):
self.patchSafeList()
# File with no timestamp.
purge_builds.ExpandAndExpire(
self.ctx, False, self.expireDate, self.file_no_timestamp
)
self.assertEqual(
self.gs_mock.call_args_list,
[
mock.call(
self.ctx,
[
"mv",
"--",
"gs://chromeos-releases/canary-channel/plain_file",
"gs://chromeos-releases-backup/canary-channel/plain_file",
],
),
],
)
def testExpireAndExpandWithTimestamp(self):
self.patchSafeList()
# File with timestamp.
purge_builds.ExpandAndExpire(
self.ctx, False, self.expireDate, self.file_with_timestamp
)
self.assertEqual(
self.gs_mock.call_args_list,
[
mock.call(
self.ctx,
[
"mv",
"--",
"gs://chromeos-releases/canary-channel/plain_file",
"gs://chromeos-releases-backup/canary-channel/plain_file",
],
),
],
)
def testExpireAndExpandDirectory(self):
self.patchSafeList()
purge_builds.ExpandAndExpire(
self.ctx, False, self.expireDate, self.directory
)
self.assertEqual(
self.gs_mock.call_args_list,
[
mock.call(
self.ctx,
[
"mv",
"--",
"gs://chromeos-releases/canary-channel/x86-alex/1.2.3/a",
"gs://chromeos-releases-backup/canary-channel/x86-alex/1.2.3/a",
],
),
mock.call(
self.ctx,
[
"mv",
"--",
"gs://chromeos-releases/canary-channel/x86-alex/1.2.3/nest/deep",
"gs://chromeos-releases-backup/canary-channel/x86-alex/1.2.3/"
"nest/deep",
],
),
],
)