blob: a8c2de4a978ca0c3bdbf48ef5eaadb156933a532 [file] [log] [blame]
# Copyright 2024 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Tests for monitor_chrome_afdo."""
import dataclasses
import datetime
from typing import List
import unittest
from afdo_tools import monitor_chrome_afdo
def arbitrary_time() -> datetime.datetime:
"""Returns an arbitrary datetime, in UTC."""
return datetime.datetime(2020, 1, 2, 3, 4, 5, 6, datetime.timezone.utc)
def arbitrary_chrome_gs_profile_name() -> monitor_chrome_afdo.ChromeGsProfile:
"""Returns an arbitrary profile name >= MIN_PROFILE_MAJOR_VERSION."""
major_cwp_version = monitor_chrome_afdo.MIN_PROFILE_MAJOR_VERSION
major_bench_version = major_cwp_version + 1
return (
f"chromeos-chrome-arm-none-{major_cwp_version}-6440.4-1716810247-"
f"benchmark-{major_bench_version}.1.6533.2-r3-redacted.afdo.xz"
)
def arbitrary_chrome_gs_profile() -> monitor_chrome_afdo.ChromeGsProfile:
"""Returns an arbitrary ChromeGsProfile."""
full_name = arbitrary_chrome_gs_profile_name()
x = monitor_chrome_afdo.ChromeGsProfile.from_full_name_if_new_enough(
last_modified=arbitrary_time(),
full_name=full_name,
)
assert x is not None, f"Profile name was too old? Name: {full_name}"
return x
def increasing_chrome_gs_profile_sequence(
count: int,
) -> List[monitor_chrome_afdo.ChromeGsProfile]:
"""Returns an iterable of successive Chrome GS profiles.
They're all successive in that:
1. Their `last_modified` are yielded in increasing order.
2. Their benchmark versions are also yielded in increasing order.
Otherwise, all attributes (profile arch, subtype, etc) will remain
consistent across all profiles.
Returns:
A list of `count` profiles.
"""
baseline = arbitrary_chrome_gs_profile()
return [
dataclasses.replace(
baseline,
last_modified=baseline.last_modified
+ datetime.timedelta(seconds=x),
cwp_timestamp=baseline.cwp_timestamp + x,
)
for x in range(count)
]
class Test(unittest.TestCase):
"""Tests for monitor_chrome_afdo."""
def test_all_profile_arch_parsing(self):
for arch in monitor_chrome_afdo.ProfileArch:
self.assertEqual(
arch, monitor_chrome_afdo.ProfileArch.parse(arch.value)
)
with self.assertRaises(ValueError):
monitor_chrome_afdo.ProfileArch.parse("not-a-profile-arch")
def test_all_profile_subtype_parsing(self):
for subtype in monitor_chrome_afdo.ProfileSubtype:
self.assertEqual(
subtype, monitor_chrome_afdo.ProfileSubtype.parse(subtype.value)
)
with self.assertRaises(ValueError):
monitor_chrome_afdo.ProfileSubtype.parse("not-a-profile-subtype")
def test_gs_profile_parsing(self):
last_modified = arbitrary_time()
profile_name = arbitrary_chrome_gs_profile_name()
self.assertEqual(
monitor_chrome_afdo.ChromeGsProfile.from_full_name_if_new_enough(
last_modified=last_modified,
full_name=profile_name,
),
monitor_chrome_afdo.ChromeGsProfile(
last_modified=last_modified,
arch=monitor_chrome_afdo.ProfileArch.ARM,
subtype=monitor_chrome_afdo.ProfileSubtype.NONE,
benchmark_part_version=monitor_chrome_afdo.ChromeVersion(
major=monitor_chrome_afdo.MIN_PROFILE_MAJOR_VERSION + 1,
minor=1,
build=6533,
patch=2,
revision=3,
),
cwp_part_version=monitor_chrome_afdo.ChromeVersion(
major=monitor_chrome_afdo.MIN_PROFILE_MAJOR_VERSION,
minor=0,
build=6440,
patch=4,
revision=0,
),
cwp_timestamp=1716810247,
),
)
def test_gs_profile_name_round_trips(self):
last_modified = arbitrary_time()
profile_name = arbitrary_chrome_gs_profile_name()
self.assertEqual(
monitor_chrome_afdo.ChromeGsProfile.from_full_name_if_new_enough(
last_modified=last_modified, full_name=profile_name
).full_name(),
profile_name,
)
def test_gs_profile_parsing_on_old_profile(self):
major_bench_version = monitor_chrome_afdo.MIN_PROFILE_MAJOR_VERSION - 1
last_modified = arbitrary_time()
profile_name = (
f"chromeos-chrome-nonsense_arch-nonsense_type-0-6440.4-1716810247-"
f"benchmark-{major_bench_version}.1.6533.2-r3-redacted.afdo.xz"
)
self.assertIsNone(
monitor_chrome_afdo.ChromeGsProfile.from_full_name_if_new_enough(
last_modified=last_modified,
full_name=profile_name,
)
)
def test_finding_newest_chrome_version_on_no_stable_ebuilds(self):
with self.assertRaisesRegex(ValueError, "^No stable Chrome ebuilds.*"):
monitor_chrome_afdo.find_newest_chrome_version(
[
"MANIFEST",
"files/",
"chromeos-chrome-9999.ebuild",
]
)
def test_finding_newest_chrome_version_multiple_ebuilds(self):
self.assertEqual(
monitor_chrome_afdo.find_newest_chrome_version(
[
"MANIFEST",
"files/",
"chromeos-chrome-9999.ebuild",
"chromeos-chrome-127.0.6533.0_rc-r1.ebuild",
"chromeos-chrome-126.0.6014.0_rc-r2.ebuild",
]
),
"127.0.6533.0",
)
def test_afdo_version_finding_works(self):
profile1, profile2, profile3 = increasing_chrome_gs_profile_sequence(3)
profiles = {
1: [profile1, profile2],
2: [profile3],
}
with self.assertRaisesRegex(ValueError, "^No available profile.*"):
monitor_chrome_afdo.find_afdo_profile_by_version(
profiles, "not a profile version"
)
self.assertIs(
monitor_chrome_afdo.find_afdo_profile_by_version(
profiles, profile2.full_name()
),
profile2,
)
def test_branch_profile_finding_works_in_simple_cases(self):
profile1, profile2, profile3 = increasing_chrome_gs_profile_sequence(3)
arch = monitor_chrome_afdo.ProfileArch.AMD64
subtype = monitor_chrome_afdo.ProfileSubtype.BIGCORE
# Assert this since a having `(arch, subtype)` as the arch/subtype of
# _all_ profiles will cause nonsense results.
self.assertNotEqual((arch, subtype), (profile2.arch, profile2.subtype))
profile2 = dataclasses.replace(profile2, arch=arch, subtype=subtype)
profiles = {
1: [profile1],
2: [profile2, profile3],
}
result = monitor_chrome_afdo.find_most_recent_branch_profile(
afdo_profiles=profiles,
arch=arch,
subtype=subtype,
branch_number=2,
)
self.assertIs(result, profile2)
with self.assertRaisesRegex(ValueError, "^Found no branch profiles.*"):
monitor_chrome_afdo.find_most_recent_branch_profile(
afdo_profiles=profiles,
arch=arch,
subtype=subtype,
branch_number=1,
)
def test_branch_profile_finding_falls_back_to_prior_branches(self):
profile1, profile2, profile3 = increasing_chrome_gs_profile_sequence(3)
arch = monitor_chrome_afdo.ProfileArch.AMD64
subtype = monitor_chrome_afdo.ProfileSubtype.BIGCORE
self.assertNotEqual((arch, subtype), (profile1.arch, profile1.subtype))
profile1 = dataclasses.replace(profile2, arch=arch, subtype=subtype)
profiles = {
1: [profile1],
2: [profile2],
3: [profile3],
}
result = monitor_chrome_afdo.find_most_recent_branch_profile(
afdo_profiles=profiles,
arch=arch,
subtype=subtype,
branch_number=3,
)
self.assertIs(result, profile1)