diff --git a/CHANGES/6313.misc b/CHANGES/6313.misc new file mode 100644 index 000000000..20ecfc319 --- /dev/null +++ b/CHANGES/6313.misc @@ -0,0 +1 @@ +Added tests for sync optimization. diff --git a/pulp_rpm/tests/functional/api/test_sync.py b/pulp_rpm/tests/functional/api/test_sync.py index fb4c0a82c..dca1fe55d 100644 --- a/pulp_rpm/tests/functional/api/test_sync.py +++ b/pulp_rpm/tests/functional/api/test_sync.py @@ -2,6 +2,7 @@ """Tests that sync rpm plugin repositories.""" import os import unittest +from random import choice from pulp_smash import cli, config from pulp_smash.pulp3.constants import MEDIA_PATH @@ -12,7 +13,8 @@ get_content, get_content_summary, get_removed_content, - delete_orphans + delete_orphans, + modify_repo, ) from pulp_rpm.tests.functional.constants import ( @@ -26,6 +28,7 @@ RPM_MODULAR_FIXTURE_URL, RPM_PACKAGE_CONTENT_NAME, RPM_PACKAGE_COUNT, + RPM_RICH_WEAK_FIXTURE_URL, RPM_UPDATERECORD_ID, RPM_UPDATED_UPDATEINFO_FIXTURE_URL, RPM_REFERENCES_UPDATEINFO_URL, @@ -37,6 +40,7 @@ gen_rpm_client, gen_rpm_remote, monitor_task, + progress_reports, ) from pulp_rpm.tests.functional.utils import set_up_module as setUpModule # noqa:F401 @@ -487,6 +491,112 @@ def test_file_decriptors(self): response = cli_client.run(cmd).stdout self.assertEqual(len(response), 0, response) + def test_optimize(self): + """Sync is no-op without changes. + + This test targets the following issue: + + `Pulp #6313 `_ + + If there are no changes, a full sync should not be done. + + Do the following: + + 1. Sync (a repo and a remote will be created automatically). + 2. Sync again to get our task dictionary. + 3. Assert an "Optimizing Sync" progress report is present. + 4. Sync again with flag "optimize=False". + 5. Assert "Optimizing Sync" progress report is absent. + # 6. **Create a new repo version. + # 7. Sync again (no flag). + # 8. Assert "Optimizing Sync" progress report is absent. + 9. Update remote to have "policy=immediate". + 10. Sync again. + 11. Assert "Optimizing Sync" progress report is absent. + 12. Create a new (different) remote. + 13. Sync using the new remote. + 14. Assert "Optimizing Sync" progress report is absent. + # 15. Sync again with the new remote. + # 16. Assert an "Optimizing Sync" progress report is present. + """ + # sync + repo, remote = self.do_test() + + # add resources to clean up + self.addCleanup(self.repo_api.delete, repo.pulp_href) + self.addCleanup(self.remote_api.delete, remote.pulp_href) + + # sync, get progress reports from task + report_list = self.sync(repository=repo, remote=remote) + + # check for an optimization progress report + optimized = self.optimize_report(progress_reports=report_list) + + # check that sync was optimized + self.assertTrue(optimized) + + # sync again with flag optimize=False + report_list = self.sync(repository=repo, remote=remote, optimize=False) + + # check for an optimization progress report + optimized = self.optimize_report(progress_reports=report_list) + + # check that sync was not optimized + self.assertFalse(optimized) + + # create a new repo version + content = choice(get_content(repo.to_dict())[RPM_PACKAGE_CONTENT_NAME]) + modify_repo(config.get_config(), repo.to_dict(), remove_units=[content]) + + # sync, get progress reports from task + report_list = self.sync(repository=repo, remote=remote) + + # check for an optimization progress report + optimized = self.optimize_report(progress_reports=report_list) + + # check that sync was not optimized + self.assertFalse(optimized) + + # update remote + body = {"policy": "immediate"} + response = self.remote_api.partial_update(remote.pulp_href, body) + monitor_task(response.task) + + # sync, get progress reports from task + report_list = self.sync(repository=repo, remote=remote) + + # check for an optimization progress report + optimized = self.optimize_report(progress_reports=report_list) + + # check that sync was not optimized + self.assertFalse(optimized) + + # create new remote + body = gen_rpm_remote() + body['url'] = RPM_RICH_WEAK_FIXTURE_URL + new_remote = self.remote_api.create(body) + + # add resource to clean up + self.addCleanup(self.remote_api.delete, new_remote.pulp_href) + + # sync with new remote + report_list = self.sync(repository=repo, remote=new_remote) + + # check for an optimization progress report + optimized = self.optimize_report(progress_reports=report_list) + + # check that sync was not optimized + self.assertFalse(optimized) + + # sync again with new remote + report_list = self.sync(repository=repo, remote=new_remote) + + # check for an optimization progress report + optimized = self.optimize_report(progress_reports=report_list) + + # check that sync was optimized + self.assertTrue(optimized) + def do_test(self, repository=None, remote=None): """Sync a repository. @@ -516,6 +626,29 @@ def do_test(self, repository=None, remote=None): monitor_task(sync_response.task) return self.repo_api.read(repo.pulp_href), self.remote_api.read(remote.pulp_href) + def sync(self, repository=None, remote=None, optimize=True): + """Sync a repository and return the task. + + Args: + repository (pulp_rpm.app.models.repository.RpmRepository): + object of RPM repository + remote (pulp_rpm.app.models.repository.RpmRemote): + object of RPM Remote + Returns (list): + list of the ProgressReport objects created from this sync + """ + repository_sync_data = RpmRepositorySyncURL(remote=remote.pulp_href, optimize=optimize) + sync_response = self.repo_api.sync(repository.pulp_href, repository_sync_data) + monitor_task(sync_response.task) + return progress_reports(sync_response.task) + + def optimize_report(self, progress_reports=[]): + """Return whether an optimize progress report exists.""" + for report in progress_reports: + if report.message == "Optimizing Sync": + return True + return False + class SyncInvalidTestCase(unittest.TestCase): """Sync a repository with a given url on the remote.""" diff --git a/pulp_rpm/tests/functional/api/test_upload.py b/pulp_rpm/tests/functional/api/test_upload.py index 555bfeaed..8c31ee826 100644 --- a/pulp_rpm/tests/functional/api/test_upload.py +++ b/pulp_rpm/tests/functional/api/test_upload.py @@ -10,8 +10,7 @@ from pulp_rpm.tests.functional.utils import ( core_client, gen_rpm_client, - monitor_task -) + monitor_task,) from pulp_rpm.tests.functional.constants import ( RPM_UNSIGNED_FIXTURE_URL, RPM_PACKAGE_FILENAME, @@ -46,7 +45,7 @@ def tearDown(self): """TearDown.""" delete_orphans() - def test_singe_request_unit_and_duplicate_unit(self): + def test_single_request_unit_and_duplicate_unit(self): """Test single request upload unit. 1. Upload a unit diff --git a/pulp_rpm/tests/functional/utils.py b/pulp_rpm/tests/functional/utils.py index ae327bf0b..9290f73f5 100644 --- a/pulp_rpm/tests/functional/utils.py +++ b/pulp_rpm/tests/functional/utils.py @@ -250,3 +250,25 @@ def init_signed_repo_configuration(): "AsciiArmoredDetachedSigningService.objects.create(name='sign-metadata'," f"script='{signing_script_path}')") ) + + +def progress_reports(task_href): + """Returns the progress reports generated by a completed task. + + Args: + task_href(str): The href of the task to monitor + + Returns: + list[ProgressReport]: List of ProgressReport objects generated during the task + + """ + completed = ["completed", "failed", "canceled"] + task = tasks.read(task_href) + while task.state not in completed: + sleep(2) + task = tasks.read(task_href) + + if task.state == "completed": + return task.progress_reports + + return []