#1627 Add test 'reuse components if added'
Merged a day ago by breilly. Opened 3 months ago by jobrauer.
jobrauer/fm-orchestrator test_reuse_components_if_added  into  master

@@ -49,7 +49,10 @@ 

      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")

@@ -115,3 +115,21 @@ 

      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"

@@ -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)

@@ -125,6 +125,11 @@ 

          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 @@ 

          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 = [

RHELBLD-317: add test_reuse_components_if_added

(a bit cleaned and rebased version of https://pagure.io/fm-orchestrator/pull-request/1607)

Just a quick note, since I did not receive any comments about the invalid scenario, i.e.:

"""
having 2 rpms previously built (batch 1, 2), adding a third one (batch 3) and rebuilding with changed-and-after"

still rebuilds the the 2nd rpm (batch 2) - the 1st one gets reused as expected. There are no log entries between 'Starting build of next batch X' and 'submitted build of' so I got a hard time following the code without the inner workings knowledge...

Am I doing something wrong? Please have a look at builds:
1) strategy 'all': https://brewweb.stage.engineering.redhat.com/brew/buildinfo?buildID=1806425
2) immediately after - strategy 'changed-and-after': https://brewweb.stage.engineering.redhat.com/brew/buildinfo?buildID=1806435
"""

I assume, my assumptions weren't correct, so this scenario is no longer covered.

rebased onto 499311f

3 months ago

rebased onto 760419c

a month ago

@mikem @breilly can you check this PR please? It is open 2 months and without any review.

This change LGTM, @jobrauer could you rebase?

rebased onto ac3de1e

8 days ago

Build ac3de1e FAILED!
Rebase or make new commits to rebuild.

rebased onto 87c83ad

7 days ago

Rebase verified, ready to merge (just in case...).

Pull-Request has been merged by breilly

a day ago