blob: 1630d800e52f10e767eb3887359f4aa344fec25a [file] [log] [blame]
# Copyright 2023 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 query.py."""
from pathlib import Path
from unittest import mock
import pytest
from chromite.lib import build_query
from chromite.test import portage_testables
# Linter seems unaware of pytest fixtures.
# pylint: disable=redefined-outer-name
# pylint: disable=unused-argument
@pytest.fixture
def fake_overlays(tmp_path):
portage_stable = portage_testables.Overlay(
root_path=tmp_path / "portage-stable", name="portage-stable"
)
chromiumos_overlay = portage_testables.Overlay(
root_path=tmp_path / "chromiumos-overlay", name="chromiumos"
)
eclass_overlay = portage_testables.Overlay(
root_path=tmp_path / "eclass-overlay", name="eclass-overlay"
)
baseboard_fake = portage_testables.Overlay(
root_path=tmp_path / "baseboard-fake",
name="baseboard-fake",
)
baseboard_fake.create_profile(
make_defaults={
"ARCH": "amd64",
"USE": "some another masked not_masked",
"USE_EXPAND": "SOME_VAR",
"SOME_VAR": "baseboard_val",
},
use_mask=["masked", "not_masked"],
use_force=["amd64"],
)
overlay_fake = portage_testables.Overlay(
root_path=tmp_path / "overlay-fake",
name="fake",
parent_overlays=[baseboard_fake],
)
overlay_fake.create_profile(
make_defaults={
"USE": "fake -another -baseboard_fake_private",
"SOME_VAR": "-* board_val",
"ANOTHER_VAR": "one_val another_val",
"USE_EXPAND": "ANOTHER_VAR",
},
profile_parents=[baseboard_fake.profiles[Path("base")]],
use_mask=["-not_masked"],
)
overlay_fake.add_package(
portage_testables.Package(
category="chromeos-base",
package="chromeos-bsp-fake",
version="0.0.1-r256",
IUSE="another internal +static",
inherit=["cros-workon", "chromeos-bsp"],
keywords="*",
)
)
overlay_fake.add_package(
portage_testables.Package(
category="chromeos-base",
package="chromeos-bsp-fake",
version="9999",
IUSE="another internal +static",
inherit=["cros-workon", "chromeos-bsp"],
keywords="~*",
)
)
baseboard_fake_private = portage_testables.Overlay(
root_path=tmp_path / "baseboard-fake-private",
name="baseboard-fake-private",
parent_overlays=[baseboard_fake],
)
baseboard_fake_private.create_profile(
make_defaults={"USE": "baseboard_fake_private"},
profile_parents=[baseboard_fake.profiles[Path("base")]],
)
overlay_fake_private = portage_testables.Overlay(
root_path=tmp_path / "overlay-fake-private",
name="fake-private",
parent_overlays=[overlay_fake],
make_conf={
"CHOST": "x86_64-pc-linux-gnu",
"USE": "internal",
},
)
overlay_fake_private.create_profile(
make_defaults={"SOME_VAR": "private_val"},
profile_parents=[
baseboard_fake_private.profiles[Path("base")],
overlay_fake.profiles[Path("base")],
],
)
overlay_fake_private.add_package(
portage_testables.Package(
category="chromeos-base",
package="chromeos-bsp-fake-private",
version="0.0.1",
IUSE="another internal +static",
inherit=["cros-workon", "chromeos-bsp"],
keywords="-* ~amd64",
)
)
overlay_fake_private.add_package(
portage_testables.Package(
category="chromeos-base",
package="chromeos-bsp-fake-private",
version="9999",
IUSE="another internal +static",
inherit=["cros-workon", "chromeos-bsp"],
keywords="~* amd64",
)
)
overlay_faux_private = portage_testables.Overlay(
root_path=tmp_path / "overlay-faux-private",
name="faux-private",
parent_overlays=[
baseboard_fake,
overlay_fake,
baseboard_fake_private,
overlay_fake_private,
],
)
overlay_faux_private.create_profile(
profile_parents=[
overlay_fake_private.profiles[Path("base")],
],
)
overlays = [
portage_stable,
chromiumos_overlay,
eclass_overlay,
baseboard_fake,
overlay_fake,
baseboard_fake_private,
overlay_fake_private,
overlay_faux_private,
]
with mock.patch(
"chromite.lib.portage_util.FindOverlays",
return_value=[str(x.path) for x in overlays],
):
# We just changed the overlays with our mock, we need to clear the
# cache.
# pylint: disable=protected-access
build_query._get_all_overlays_by_name.cache_clear()
yield overlays
def test_query_overlays(fake_overlays):
"""Test listing all overlays."""
overlays = {x.name: x for x in build_query.Overlay.find_all()}
assert overlays["baseboard-fake"].board_name is None
assert overlays["baseboard-fake"].is_private is False
assert overlays["fake"].board_name == "fake"
assert overlays["fake"].is_private is False
assert overlays["baseboard-fake-private"].board_name is None
assert overlays["baseboard-fake-private"].is_private is True
assert overlays["fake-private"].board_name == "fake"
assert overlays["fake-private"].is_private is True
def test_query_profiles(fake_overlays):
"""Test listing all profiles."""
profiles = list(build_query.Profile.find_all())
assert profiles[0].overlay.name == "baseboard-fake"
assert profiles[0].name == "base"
assert profiles[0].parents == []
assert profiles[1].overlay.name == "fake"
assert profiles[1].name == "base"
assert profiles[1].parents == [profiles[0]]
assert profiles[2].overlay.name == "baseboard-fake-private"
assert profiles[2].name == "base"
assert profiles[2].parents == [profiles[0]]
assert profiles[3].overlay.name == "fake-private"
assert profiles[3].name == "base"
assert profiles[3].parents == [profiles[2], profiles[1]]
def test_query_boards(fake_overlays):
"""Test listing all boards."""
board = (
build_query.Query(build_query.Board)
.filter(lambda x: x.name == "fake")
.one()
)
assert board.arch == "amd64"
overlay = [x for x in fake_overlays if x.name == "fake-private"][0]
assert board.top_level_overlay.path == overlay.path
assert (
board.top_level_profile.path == overlay.profiles[Path("base")].full_path
)
def test_query_ebuilds(fake_overlays):
"""Test listing all ebuilds."""
ebuilds = list(build_query.Ebuild.find_all())
found_packages = {str(ebuild) for ebuild in ebuilds}
assert found_packages == {
"chromeos-base/chromeos-bsp-fake-0.0.1-r256::fake",
"chromeos-base/chromeos-bsp-fake-9999::fake",
"chromeos-base/chromeos-bsp-fake-private-0.0.1::fake-private",
"chromeos-base/chromeos-bsp-fake-private-9999::fake-private",
}
assert all(x.eapi == 7 for x in ebuilds)
assert all(x.eclasses == ["cros-workon", "chromeos-bsp"] for x in ebuilds)
assert all(x.iuse == {"another", "internal", "static"} for x in ebuilds)
assert all(x.iuse_default == {"static"} for x in ebuilds)
@pytest.mark.parametrize(
["board_name", "is_variant"],
[
("fake", False),
("faux", True),
],
)
def test_is_variant(fake_overlays, board_name, is_variant):
"""Test the is_variant property of boards."""
board = (
build_query.Query(build_query.Board)
.filter(lambda x: x.name == board_name)
.one()
)
assert board.is_variant == is_variant
@pytest.mark.parametrize(
["cpvr", "arch", "expected_stability"],
[
(
"chromeos-base/chromeos-bsp-fake-0.0.1-r256",
"amd64",
build_query.Stability.STABLE,
),
(
"chromeos-base/chromeos-bsp-fake-9999",
"amd64",
build_query.Stability.UNSTABLE,
),
(
"chromeos-base/chromeos-bsp-fake-private-0.0.1",
"amd64",
build_query.Stability.UNSTABLE,
),
(
"chromeos-base/chromeos-bsp-fake-private-0.0.1",
"arm",
build_query.Stability.BAD,
),
(
"chromeos-base/chromeos-bsp-fake-private-9999",
"arm",
build_query.Stability.UNSTABLE,
),
(
"chromeos-base/chromeos-bsp-fake-private-9999",
"amd64",
build_query.Stability.STABLE,
),
],
)
def test_ebuild_stability(fake_overlays, cpvr, arch, expected_stability):
"""Test the ebuild stability evaluator."""
ebuild = (
build_query.Query(build_query.Ebuild)
.filter(lambda ebuild: ebuild.package_info.cpvr == cpvr)
.one()
)
assert ebuild.get_stability(arch) == expected_stability
def test_make_conf_vars(fake_overlays):
"""Test reading make.conf variables from an overlay."""
overlay = (
build_query.Query(build_query.Overlay)
.filter(lambda overlay: overlay.name == "fake-private")
.one()
)
assert overlay.make_conf_vars == {
"CHOST": "x86_64-pc-linux-gnu",
"USE": "internal",
}
def test_overlay_parents(fake_overlays):
overlays = {x.name: x for x in build_query.Overlay.find_all()}
assert list(overlays["baseboard-fake-private"].parents) == [
overlays["portage-stable"],
overlays["chromiumos"],
overlays["eclass-overlay"],
overlays["baseboard-fake"],
]
def test_use_flags(fake_overlays):
"""Test getting the USE flags on a board."""
board = (
build_query.Query(build_query.Board)
.filter(lambda x: x.name == "fake")
.one()
)
assert board.use_flags == {
"amd64",
"board_use_fake",
"not_masked",
"some",
"fake",
"internal",
"some_var_board_val",
"some_var_private_val",
"another_var_one_val",
"another_var_another_val",
}
def test_use_flags_set(fake_overlays):
"""Test querying the flags set by a profile."""
overlay = (
build_query.Query(build_query.Overlay)
.filter(lambda overlay: overlay.name == "baseboard-fake")
.one()
)
profile = overlay.profiles[0]
assert profile.use_flags_set == {
"amd64",
"some",
"another",
"masked",
"not_masked",
"some_var_baseboard_val",
}
def test_use_flags_unset(fake_overlays):
"""Test querying the flags unset by a profile."""
overlay = (
build_query.Query(build_query.Overlay)
.filter(lambda overlay: overlay.name == "fake")
.one()
)
profile = overlay.profiles[0]
assert profile.use_flags_unset == {
"another",
"baseboard_fake_private",
"some_var_*",
}
def test_masked_use_flags(fake_overlays):
"""Test getting the masked_use_flags on a profile."""
board = (
build_query.Query(build_query.Board)
.filter(lambda x: x.name == "fake")
.one()
)
assert board.top_level_profile.masked_use_flags == {"masked"}
def test_query_one(fake_overlays):
"""Test .one() on a query which yields one result."""
board = (
build_query.Query(build_query.Board)
.filter(lambda x: x.name == "fake")
.one()
)
assert board.name == "fake"
def test_query_one_fail_zero(fake_overlays):
"""Test .one() on a query which yields zero results fails."""
with pytest.raises(StopIteration):
build_query.Query(build_query.Board).filter(
lambda x: x.name == "notfake"
).one()
def test_query_one_fail_multiple(fake_overlays):
"""Test .one() on a query which yields multiple results fails."""
with pytest.raises(ValueError):
build_query.Query(build_query.Ebuild).one()
def test_query_one_or_none(fake_overlays):
"""Test .one_or_none() on a query which yields no results returns None."""
board = (
build_query.Query(build_query.Board)
.filter(lambda x: x.name == "notfake")
.one_or_none()
)
assert not board
def test_query_all(fake_overlays):
"""Test .all() on a query."""
boards = build_query.Query(build_query.Board).all()
assert boards == [build_query.Board("fake"), build_query.Board("faux")]
def test_resolve_incremental_variable(fake_overlays):
"""Test correctness Profile.resolve_incremental_variable."""
board = (
build_query.Query(build_query.Board)
.filter(lambda x: x.name == "fake")
.one()
)
assert board.top_level_profile.resolve_var_incremental("SOME_VAR") == {
"board_val",
"private_val",
}