diff --git a/releasenotes/notes/add-delete-by-uuid-6266652db1c8bb98.yaml b/releasenotes/notes/add-delete-by-uuid-6266652db1c8bb98.yaml new file mode 100644 index 0000000..e008ada --- /dev/null +++ b/releasenotes/notes/add-delete-by-uuid-6266652db1c8bb98.yaml @@ -0,0 +1,6 @@ +--- +features: + - New option delete_run_by_uuid, which allows for the deletion of a run + specified by a given uuid. + - New option delete_test_runs_by_uuid, which allows for the deletion of + all test runs associated with a given run uuid. diff --git a/subunit2sql/db/api.py b/subunit2sql/db/api.py index a4b581c..dcaf291 100644 --- a/subunit2sql/db/api.py +++ b/subunit2sql/db/api.py @@ -1194,6 +1194,50 @@ def delete_old_test_runs(expire_age=186, session=None): synchronize_session=False) +def delete_run_by_uuid(run_uuid, session=None): + """Delete a single test run based on its uuid. + + :param str uuid: The uuid of the run that will be deleted. + :param session: Optional session object. if one isn't provided, a + new session will be created. + """ + session = session or get_session() + run_id = get_run_id_from_uuid(run_uuid, session) + + # find and delete any runs + db_utils.model_query(models.Run, session).filter( + models.Run.uuid == run_uuid).delete(synchronize_session=False) + # search for any metadata linked to the run uuid + db_utils.model_query(models.RunMetadata, session).filter( + models.RunMetadata.run_id == run_id).delete(synchronize_session=False) + + +def delete_test_runs_by_run_uuid(run_uuid, session=None): + """Delete all test runs included in a given run + + :param str uuid: The uuid of the run that will be deleted. + :param session: Optional session object. if one isn't provided, a + new session will be created. + """ + session = session or get_session() + + # find and delete all runs associated the given run + test_runs = get_test_runs_by_run_id(run_uuid, session) + test_run_ids = [x.id for x in test_runs] + for test_run_id in test_run_ids: + db_utils.model_query(models.TestRun, session). \ + filter(models.TestRun.id == test_run_id). \ + delete(synchronize_session=False) + # Find and delete metadata for this test run + db_utils.model_query(models.TestRunMetadata, session). \ + filter(models.TestRunMetadata.test_run_id == test_run_id). \ + delete(synchronize_session=False) + # find and delete attachements for this test run + db_utils.model_query(models.Attachments, session). \ + filter(models.Attachments.test_run_id == test_run_id). \ + delete(synchronize_session=False) + + def get_id_from_test_id(test_id, session=None): """Return the id (uuid primary key) for a test given it's test_id value diff --git a/subunit2sql/tests/db/test_api.py b/subunit2sql/tests/db/test_api.py index 425cc43..e7cef78 100644 --- a/subunit2sql/tests/db/test_api.py +++ b/subunit2sql/tests/db/test_api.py @@ -487,7 +487,7 @@ class TestDatabaseAPI(base.TestCase): self.assertIn(timestamp_b, result.keys()) for timestamp in result: if timestamp.replace( - microsecond=0) == timestamp_a.replace(microsecond=0): + microsecond=0) == timestamp_a.replace(microsecond=0): self.assertEqual(5, result[timestamp]) else: self.assertEqual(2, result[timestamp]) @@ -613,6 +613,49 @@ class TestDatabaseAPI(base.TestCase): self.assertEqual(1, len(api.get_test_run_metadata(test_run_b.id))) self.assertEqual(0, len(api.get_test_run_metadata(test_run_a.id))) + def test_delete_run_by_uuid(self): + metadata_a = {'key': 'This is the metadata we\'re keeping'} + metadata_b = {'key': 'This metadata should be removed'} + run_a = api.create_run() + run_b = api.create_run() + uuid_to_delete = run_a.uuid + api.add_run_metadata(metadata_a, run_a.id) + api.add_run_metadata(metadata_b, run_b.id) + api.delete_run_by_uuid(uuid_to_delete) + runs = api.get_all_runs() + self.assertEqual(1, len(runs)) + self.assertEqual(1, api.get_session().query( + models.RunMetadata.id).count()) + self.assertEqual(run_b.id, runs[0].id) + self.assertEqual(1, len(api.get_run_metadata(run_b.uuid))) + self.assertEqual(0, len(api.get_run_metadata(run_a.uuid))) + + def test_delete_test_runs_by_run_uuid(self): + # create runs + run_a = api.create_run() + run_b = api.create_run() + uuid_to_delete = run_a.uuid + # create test runs + test = api.create_test('fake_test') + test_run_a = api.create_test_run(test.id, run_a.id, 'fail', + start_time=datetime.datetime( + 1914, 6, 28, 10, 45, 0)) + test_run_b = api.create_test_run(test.id, run_b.id, 'fail', + start_time=datetime.datetime.utcnow()) + # initialize and metadata to test_runs + metadata_a = { + 'key': 'this test belongs to the run we are deleting from'} + metadata_b = { + 'key': 'this test belongs to the run we are leaving alone'} + api.add_test_run_metadata(metadata_a, test_run_a.id) + api.add_test_run_metadata(metadata_b, test_run_b.id) + api.delete_test_runs_by_run_uuid(uuid_to_delete) + test_runs = api.get_all_test_runs() + self.assertEqual(1, len(test_runs)) + self.assertEqual(test_run_b.id, test_runs[0].id) + self.assertEqual(1, len(api.get_test_run_metadata(test_run_b.id))) + self.assertEqual(0, len(api.get_test_run_metadata(test_run_a.id))) + def test_get_run_metadata(self): run_a = api.create_run() run_b = api.create_run()