Add test 'reuse components if added'

This commit is contained in:
jobrauer
2020-05-20 11:36:58 +02:00
parent 85a61ac07e
commit 87c83ad0b8
4 changed files with 137 additions and 1 deletions

View File

@@ -49,7 +49,10 @@ def scenario(request, test_env):
scenario configuration.
"""
scenario_name = request.function.__name__.split("test_", 1)[1]
return test_env["testdata"][scenario_name]
scenario = test_env["testdata"].get(scenario_name)
if not scenario:
pytest.skip("No test scenario in 'test.env' for: {}".format(request.function.__name__))
return scenario
@pytest.fixture(scope="function")

View File

@@ -115,3 +115,21 @@ testdata:
build_id: 3345
module: testmodule
branch: test-scratch-final-mmd
reuse_components_if_removed_1:
#...
reuse_components_if_removed_n:
#...
reuse_components_if_added_1:
#...
reuse_components_if_added_n:
# reuse_components_if_added_n or reuse_components_if_removed_n, where n = {1, 2, ...}
# Same test case divided into different test functions to enable parallel execution.
# If any of these scenarios is missing, the appropriate test will simply be skipped.
module: testmodule
branch: test-reuse-components-if-added-2
# indexes of RPMs found in the test branch modulemd
first_build: [0, 2]
second_build: [0, 1, 2]
expected_reused: [0]
expected_rebuilt: [1, 2]
rebuild_strategy: "changed-and-after"

View File

@@ -0,0 +1,96 @@
import copy
def extracted_test_function(repo, pkg_util, scenario):
"""Test if previous components are reused properly, after components are added/removed.
Prerequisites:
EMPTY (no components/RPMs) module MD file
Steps:
1) Make changes to the modulemd according to test scenario (first build)
2) Make a clean build (rebuild strategy : all).
3) Add/remove RPMs according to test scenario (second build)
4) Rebuild, rebuild strategy according to test scenario
5) Revert to the initial state.
:param utils.Repo repo: repo fixture
:param utils.PackagingUtility pkg_util: pkg_util fixture
:param dict scenario: see example.test.env
"""
test_rpms = repo.components
# Prepare test data from test.env scenario
first_build_rpms = {test_rpms[i] for i in scenario["first_build"]}
second_build_rpms = {test_rpms[i] for i in scenario["second_build"]}
expected_reused = {test_rpms[i] for i in scenario["expected_reused"]}
expected_rebuilt = {test_rpms[i] for i in scenario["expected_rebuilt"]}
rebuild_strategy = scenario["rebuild_strategy"]
# Save initial state
original_metadata = repo.modulemd
original_rpms = repo.modulemd["data"]["components"]["rpms"]
# Prepare initial build metadata & push
tmp_metadata = copy.deepcopy(original_metadata)
tmp_metadata["data"]["components"]["rpms"] = {}
for rpm in first_build_rpms:
tmp_metadata["data"]["components"]["rpms"][rpm] = original_rpms[rpm]
repo.write_to_modulemd(tmp_metadata)
repo.add_all_commit_and_push(f'1st build: "{first_build_rpms}"')
try:
# Make an initial build (to be later reused)
builds = pkg_util.run("--watch", "--optional", "rebuild_strategy=all")
assert len(builds) == 1, "Initial build failed!"
# Prepare 2nd build metadata & push
tmp_metadata["data"]["components"]["rpms"] = {}
for rpm in second_build_rpms:
tmp_metadata["data"]["components"]["rpms"][rpm] = original_rpms[rpm]
repo.write_to_modulemd(tmp_metadata)
repo.add_all_commit_and_push(f'2nd build: "{second_build_rpms}"')
# Make a new build
builds = pkg_util.run("--watch", "--optional", f"rebuild_strategy={rebuild_strategy}")
assert len(builds) == 1, "Second (re)build failed!"
build = builds[0]
# we don"t care about module-build-macros
build_components = [c for c in build.components() if c["package"] != "module-build-macros"]
# Partition components by "reused" state - package name only
reused_msg = "Reused component from previous module build"
actually_reused = {
c["package"] for c in build_components if c["state_reason"] == reused_msg
}
actually_rebuilt = {
c["package"] for c in build_components if c["state_reason"] != reused_msg
}
assert actually_reused == expected_reused
assert actually_rebuilt == expected_rebuilt
finally: # Revert the change
repo.write_to_modulemd(original_metadata)
repo.add_all_commit_and_push("Revert")
# Each function needs its own test branch due to parallel execution.
# Module branch provides data - i.e. RPM components - and test.env provides
# scenario to be executed, i.e. which RPMs go to the 1st and 2nd build
# as well as expected result - see test.env example.
def test_reuse_components_if_added_1(repo, pkg_util, scenario):
extracted_test_function(repo, pkg_util, scenario)
def test_reuse_components_if_added_2(repo, pkg_util, scenario):
extracted_test_function(repo, pkg_util, scenario)
def test_reuse_components_if_removed_1(repo, pkg_util, scenario):
extracted_test_function(repo, pkg_util, scenario)
def test_reuse_components_if_removed_2(repo, pkg_util, scenario):
extracted_test_function(repo, pkg_util, scenario)

View File

@@ -124,6 +124,11 @@ class Repo:
self._modulemd = None
self._version = None
@property
def modulemd_path(self):
"""Modulemd file absolute path"""
return os.path.join(os.path.abspath(os.curdir), self.module_name + ".yaml")
@property
def modulemd(self):
"""Modulemd file as read from the repo
@@ -160,6 +165,20 @@ class Repo:
elif self._version == 2:
return self._modulemd["data"]["dependencies"][0]["buildrequires"].get("platform")
def write_to_modulemd(self, content_yaml):
"""Write new content (replace) to the modulemd file
:param dict content_yaml: module metadata dictionary
"""
with open(self.modulemd_path, 'w') as md_file:
yaml.dump(content_yaml, md_file, sort_keys=False)
def add_all_commit_and_push(self, message="Bump"):
"""Add all current changes and commit with a custom message"""
git("add", "--all")
git("commit", "--allow-empty", "-m", message)
git("push")
def bump(self):
"""Create a "bump" commit"""
args = [