From d897c75e00043a48ce3f988362fd8cde687642be Mon Sep 17 00:00:00 2001 From: Ruud Beukema <beukema@astron.nl> Date: Thu, 18 May 2017 14:50:23 +0000 Subject: [PATCH] Task #10813: Added about 35 tests. See the ticket (note 6) for my remarks. --- .../tests/t_radb.py | 417 +++++++++++++++++- 1 file changed, 412 insertions(+), 5 deletions(-) diff --git a/SAS/ResourceAssignment/ResourceAssignmentDatabase/tests/t_radb.py b/SAS/ResourceAssignment/ResourceAssignmentDatabase/tests/t_radb.py index 5f132bb5abb..694fba7a5fb 100755 --- a/SAS/ResourceAssignment/ResourceAssignmentDatabase/tests/t_radb.py +++ b/SAS/ResourceAssignment/ResourceAssignmentDatabase/tests/t_radb.py @@ -24,6 +24,7 @@ import psycopg2 import os from dateutil import parser import logging +from datetime import timedelta logger = logging.getLogger(__name__) @@ -53,8 +54,8 @@ class ResourceAssignmentDatabaseTest(unittest.TestCase): # These are applied in given order to set up test db # Note: cannot use create_and_populate_database.sql since '\i' is not understood by cursor.execute() - sql_basepath = os.environ['LOFARROOT'] + "/share/radb/sql/" - sql_createdb_paths = [sql_basepath + "create_database.sql", + sql_basepath = os.environ['LOFARROOT'] + "/share/radb/sql" + sql_createdb_paths = [sql_basepath + "/create_database.sql", sql_basepath + "/add_resource_allocation_statics.sql", sql_basepath + "/add_virtual_instrument.sql", sql_basepath + "/add_notifications.sql", @@ -258,9 +259,415 @@ class ResourceAssignmentDatabaseTest(unittest.TestCase): # # - def test_getTaskStatuses_contains_scheduled(self): - stat = self.radb.getTaskStatuses() - self.assertTrue('scheduled' in str(stat)) + def test_getTaskStatuses_succeeds(self): + """ Verifies if radb.getTaskStatuses() successfully fetches all expected task statuses """ + + expected_statuses = [ + {'id': 200, 'name': 'prepared'}, + {'id': 300, 'name': 'approved'}, + {'id': 320, 'name': 'on_hold'}, + {'id': 335, 'name': 'conflict'}, + {'id': 350, 'name': 'prescheduled'}, + {'id': 400, 'name': 'scheduled'}, + {'id': 500, 'name': 'queued'}, + {'id': 600, 'name': 'active'}, + {'id': 900, 'name': 'completing'}, + {'id': 1000, 'name': 'finished'}, + {'id': 1100, 'name': 'aborted'}, + {'id': 1150, 'name': 'error'}, + {'id': 1200, 'name': 'obsolete'}] + + statuses = self.radb.getTaskStatuses() + + self.assertEquals(statuses, expected_statuses) + + def test_getTaskStatusNames_succeeds(self): + """ Verifies if radb.getTaskStatusNames() successfully fetches all expected task status names """ + + expected_names = ['prepared', 'approved', 'on_hold', 'conflict', 'prescheduled', 'scheduled', 'queued', + 'active', 'completing', 'finished', 'aborted', 'error', 'obsolete'] + + names = self.radb.getTaskStatusNames() + + self.assertEqual(sorted(expected_names), sorted(names)) + + def test_getTaskStatusId_wrong_status_fails(self): + """ Verifies if radb.getTaskStatusId() raises an Exception if the idea of an unknown status is requested """ + + wrong_status = 'willywonka' + + self.assertRaises(KeyError, self.radb.getTaskStatusId, wrong_status) + + def test_getTaskStatusId_right_status_succeeds(self): + """ Verifies if radb.getTaskStatusId() successfully fetches the expected status id for a given status. """ + + status = 'scheduled' + expected_status_id = 400 + + status_id = self.radb.getTaskStatusId(status) + + self.assertEqual(status_id, expected_status_id) + + def test_getTaskTypes_succeeds(self): + """ Verifies if radb.getTaskTypes() successfully fetches all expected task types """ + + expected_task_types = [ + {'id': 0, 'name': 'observation'}, + {'id': 1, 'name': 'pipeline'}, + {'id': 2, 'name': 'reservation'}] + + task_types = self.radb.getTaskTypes() + + self.assertEqual(task_types, expected_task_types) + + def test_getTaskTypeNames_succeeds(self): + """ Verifies if radb.getTaskTypeNames() successfully fetches all expected task type names """ + + expected_task_type_names = ['observation', 'pipeline', 'reservation'] + + task_type_names = self.radb.getTaskTypeNames() + + self.assertEqual(task_type_names, expected_task_type_names) + + def test_getTaskTypeId_wrong_type_name_fails(self): + """ Verifies if radb.getTaskTypeId() raises an exception if a type id is requested for a wrong type name """ + + wrong_type_name = 'willywonka' + + self.assertRaises(KeyError, self.radb.getTaskTypeId, wrong_type_name) + + def test_getTaskTypeId_right_type_name_succeeds(self): + """ Verifies if radb.getTaskTypeId() successfully fetches the type id for a given type name. """ + + type_name = 'reservation' + expected_type_id = 2 + + type_id = self.radb.getTaskTypeId(type_name) + + self.assertEqual(type_id, expected_type_id) + + # TODO: once merged with RT-Task10811 replace the old claim statuses by the new ones + def test_getResourceClaimStatuses_succeeds(self): + """ Verifies if radb.getResourceClaimStatuses() successfully fetches all expected claim statuses. """ + + expected_claim_statuses = [ + {'id': 0, 'name': 'claimed'}, + {'id': 1, 'name': 'allocated'}, + {'id': 2, 'name': 'conflict'}] + # expected_claim_statuses = [ + # {'id': 0, 'name': 'tentative'}, + # {'id': 1, 'name': 'claimed'}, + # {'id': 2, 'name': 'conflict'}] + + claim_statuses = self.radb.getResourceClaimStatuses() + + self.assertEqual(claim_statuses, expected_claim_statuses) + + # TODO: once merged with RT-Task10811 replace the old claim statuses by the new ones + def test_getResourceClaimStatusNames_succeeds(self): + """ Verifies if radb.getResourceClaimStatusNames() successfully fetches all expected claim status names. """ + + expected_claim_status_names = ['claimed', 'allocated', 'conflict'] + #expected_claim_status_names = ['tentative', 'claimed', 'conflict'] + + claim_status_names = self.radb.getResourceClaimStatusNames() + + self.assertEqual(claim_status_names, expected_claim_status_names) + + def test_getResourceClaimStatusId_wrong_claim_name_fails(self): + """ Verifies if radb.getResourceClaimStatusId() raises an exception if a claim status id is requested for wrong + claim name. """ + + wrong_claim_name = 'willywonka' + + self.assertRaises(KeyError, self.radb.getResourceClaimStatusId, wrong_claim_name) + + def test_getResourceClaimStatusId_right_claim_name_succeeds(self): + """ Verifies if radb.getResourceClaimStatusId() successfully fetches the expected claim ID for a given claim + name. """ + + claim_name = 'conflict' + expected_claim_id = 2 + + claim_id = self.radb.getResourceClaimStatusId(claim_name) + + self.assertEqual(claim_id, expected_claim_id) + + def test_getTasksTimeWindow_no_ids_fails(self): + """ Verify if radb.getTasksTimeWindow() raises an exception when called with an empty ID lists for every ID + type. """ + + self.assertRaises(KeyError, self.radb.getTasksTimeWindow, task_ids=[], mom_ids=[], otdb_ids=[]) + + def test_getTasksTimeWindow_multiple_kinds_of_ids_fails(self): + """ Verify if radb.getTasksTimeWindow() raises an exception when called with IDs of more than one type. """ + + task_ids = [0, 1, 2, 3] + mom_ids = [4, 5, 6, 7] + otdb_ids = [8, 9, 10, 11] + + self.assertRaises(KeyError, self.radb.getTasksTimeWindow, task_ids, mom_ids, otdb_ids) + + def test_getTasksTimeWindow_empty_ids_list_succeeds(self): + """ Verify if radb.getTasksTimeWindow() returns an empty list when requesting a time window for an empty list + of IDs. """ + + time_windows = [self.radb.getTasksTimeWindow([], None, None), + self.radb.getTasksTimeWindow(None, [], None), + self.radb.getTasksTimeWindow(None, None, [])] + + expected_time_windows = [[], [], []] + self.assertItemsEqual(time_windows, expected_time_windows) + + def test_getTasksTimeWindow_empty_db_returns_no_time_window_succeeds(self): + """ Verify if radb.getTasksTimeWindow() returns an invalid time window when requesting a time window for a + non-existing task. """ + + # Ask time window for a non-existing task id + time_window = self.radb.getTasksTimeWindow([0], None, None) + + time_window = [time_window['min_starttime'], time_window['max_endtime']] + expected_time_window = [None, None] + self.assertItemsEqual(time_window, expected_time_window) + + def test_getTasksTimeWindow_normal_use_succeeds(self): + """ Verify if radb.getTasksTimeWindow() successfully return the expected time window when requesting a time + window for an existing task. """ + + # Shoot a task into RADB which time window can later be queried + starttime = '2017-05-10 10:00:00' + endtime = '2017-05-10 12:00:00' + mom_id = 1 + otdb_id = 2 + task_id = self.radb.insertSpecificationAndTask(mom_id=mom_id, otdb_id=otdb_id, task_status="prescheduled", + task_type="observation", starttime=starttime, endtime=endtime, + content="", cluster="CEP4")['task_id'] + + # Now query RADB for time_window based on task_id, mom_id, and otdb_id + time_windows = [self.radb.getTasksTimeWindow([task_id], None, None), + self.radb.getTasksTimeWindow(None, [mom_id], None), + self.radb.getTasksTimeWindow(None, None, [otdb_id])] + + # The time_window based on task_id, mom_id, and otdb_id should be the same + expected_time_windows = 3*[{'max_endtime': parser.parse(endtime), 'min_starttime': parser.parse(starttime)}] + self.assertItemsEqual(time_windows, expected_time_windows) + + def test_getTasks_no_ids_fails(self): + """ Verify if radb.getTasks() raises an exception when called with an empty ID lists for every ID type. """ + + self.assertRaises(KeyError, self.radb.getTasks, task_ids=[], mom_ids=[], otdb_ids=[]) + + def test_getTasks_multiple_kinds_of_ids_fails(self): + """ Verify if radb.getTasks() raises an exception when called with filled ID lists for multiple ID types. """ + + task_ids = [0, 1, 2, 3] + mom_ids = [4, 5, 6, 7] + otdb_ids = [8, 9, 10, 11] + + self.assertRaises(KeyError, self.radb.getTasks, task_ids=task_ids, mom_ids=mom_ids, otdb_ids=otdb_ids) + + def test_getTasks_empty_ids_list_succeeds(self): + tasks = [self.radb.getTasks(task_ids=[], mom_ids=None, otdb_ids=None), + self.radb.getTasks(task_ids=None, mom_ids=[], otdb_ids=None), + self.radb.getTasks(task_ids=None, mom_ids=None, otdb_ids=[])] + + expected_tasks = [[], [], []] + self.assertItemsEqual(tasks, expected_tasks) + + def test_getTasks_empty_db_returns_empty_list_succeeds(self): + """ Verify if radb.getTasks() successfully returns an empty list when called with a task ID that is non-existing + in RADB. """ + + tasks = self.radb.getTasks(task_ids=[0]) + + self.assertEqual(tasks, []) + + def test_getTasks_normal_use_succeeds(self): + """ Verify if radb.getTasks() successfully returns the expected tasks when requesting tasks related to an + existing task. """ + + # Shoot a task into RADB which can later be fetched + task_id = self.radb.insertSpecificationAndTask(mom_id=1, otdb_id=2, task_status="prescheduled", + task_type="observation", starttime='2017-05-10 10:00:00', + endtime='2017-05-10 12:00:00', + content="", cluster="CEP4")['task_id'] + + # Now query RADB for the task based on task_id + task = self.radb.getTasks(task_ids=[task_id])[0] + + # The task's task ID should be the same to pass this test + self.assertEqual(task['id'], task_id) + + def test_getTask_no_ids_fails(self): + """ Verify if radb.getTask() raises an exception when called without arguments. """ + + self.assertRaises(KeyError, self.radb.getTask) + + def test_getTask_multiple_kinds_of_ids_fails(self): + """ Verify if radb.getTask() raises an exception when called with multiple ID types defined. """ + self.assertRaises(KeyError, self.radb.getTask, 1, 2, 3, 4) + + def test_getTask_empty_db_returns_none_succeeds(self): + """ Verify if radb.getTask() successfully returns an None when called with a task ID that doesn't exist in + RADB. """ + + task = self.radb.getTask(id=0) + + self.assertIsNone(task) + + + def test_getTask_normal_use_succeeds(self): + """ Verify if radb.getTask() successfully returns the expected task when requested to. """ + + # Shoot a task into RADB which fetched + task_id = self.radb.insertSpecificationAndTask(mom_id=1, otdb_id=2, task_status="prescheduled", + task_type="observation", starttime='2017-05-10 10:00:00', + endtime='2017-05-10 12:00:00', + content="", cluster="CEP4")['task_id'] + + task = self.radb.getTask(id=task_id) + + self.assertEqual(task['id'], task_id) + + def test_insertTask_with_invalid_specification_id_raises_exception(self): + """ Verify if radb.insertTask() raises an exception when called with non-existing specification ID """ + + self.assertRaises(Exception, self.radb.insertTask, 0, 0, 'conflict', 'observation', 1) + + def test_insertTask_with_invalid_id_type_raises_exception(self): + """ Verify if radb.insertTask() raises an exception when called with illegal mom_id and otdb_id types """ + + # Insert a specification in order to be sure we use a valid specification_id + spec_id = self.radb.insertSpecification(starttime='2017-05-10 10:00:00', endtime='2017-05-10 12:00:00', + content="", cluster="CEP4") + + self.assertRaises(Exception, self.radb.insertTask, 'monkey see', 'is monkey do', 'conflict', 'observation', + spec_id) + + # TODO : discuss with Jorrit whether this test covers the intent of the insertTask() function. Should it pass? + def test_insertTask_with_invalid_id_value_raises_exception(self): + """ Verify if radb.insertTask() raises an exception when called with invalid mom_id and otdb_id values """ + + # Insert a specification in order to be sure we use a valid specification_id + spec_id = self.radb.insertSpecification(starttime='2017-05-10 10:00:00', endtime='2017-05-10 12:00:00', + content="", cluster="CEP4") + + self.assertRaises(Exception, self.radb.insertTask, -1, -1, 'conflict', 'observation', spec_id) + + def test_insertTask_with_invalid_task_status_raises_exception(self): + """ Verify if radb.insertTask() raises an exception when called with invalid task status """ + + # Insert a specification in order to be sure we use a valid specification_id + specification_id = self.radb.insertSpecification(starttime='2017-05-10 10:00:00', + endtime='2017-05-10 12:00:00', + content="", cluster="CEP4") + + self.assertRaises(Exception, self.radb.insertTask, 0, 0, 'willywonka', 'observation', specification_id) + + def test_insertTask_with_invalid_task_type_raises_exception(self): + """ Verify if radb.insertTask() raises an exception when called with invalid task type """ + + # Insert a specification in order to be sure we use a valid specification_id + specification_id = self.radb.insertSpecification(starttime='2017-05-10 10:00:00', + endtime='2017-05-10 12:00:00', + content="", cluster="CEP4") + + self.assertRaises(Exception, self.radb.insertTask, 0, 0, 'conflict', 'willywonka', specification_id) + + def test_insertTask_normal_use_succeeds(self): + """ Verify if radb.insertTask() successfully inserts a task when called with valid arguments. """ + + sample_starttime = '2017-05-10 10:00:00' + sample_endtime = '2017-05-10 12:00:00' + sample_task = { + 'id': 1, + 'starttime': parser.parse(sample_starttime), + 'endtime': parser.parse(sample_endtime), + 'cluster': 'CEP4', + 'status': 'conflict', + 'status_id': 335, + 'type': 'observation', + 'type_id': 0, + 'mom_id': 0, + 'otdb_id': 0, + 'blocked_by_ids': [], + 'predecessor_ids': [], + 'successor_ids': [], + 'duration': (parser.parse(sample_endtime) - parser.parse(sample_starttime)).seconds, + } + + # Insert a specification in order to be sure we use a valid specification_id + sample_task['specification_id'] = self.radb.insertSpecification(starttime=sample_starttime, + endtime=sample_endtime, + cluster=sample_task['cluster'], + content='',) + + task_id = self.radb.insertTask(sample_task['mom_id'], sample_task['otdb_id'], sample_task['status'], + sample_task['type'], sample_task['specification_id']) + task = self.radb.getTask(id=task_id) + + self.assertEqual(task, sample_task) + + def test_deleteTask_with_non_excisting_task_id_fails(self): + """ Verify if radb.deleteTask() fails when called with a non-excisting task ID. """ + + successfully_deleted = self.radb.deleteTask(0) + + self.assertFalse(successfully_deleted) + + # TODO: discuss with Jorrit whether one would expect radb.getSpecification() to NOT return a specification once the + # TODO: task has been deleted, since changes to the task table cascades onto that of the specifications? + def test_deleteTask_removes_task_and_specification_successfully(self): + """ Verify if radb.deleteTask() successfully deletes the expected task and specification when given a task + ID. """ + + # Shoot a task and corresponding specification into RADB which can later be deleted + task = self.radb.insertSpecificationAndTask(mom_id=1, otdb_id=2, task_status="prescheduled", + task_type="observation", starttime='2017-05-10 10:00:00', + endtime='2017-05-10 12:00:00', content="", cluster="CEP4") + task_id = task['task_id'] + spec_id = task['specification_id'] + + successfully_deleted = self.radb.deleteTask(task_id) + + self.assertTrue(successfully_deleted) + self.assertIsNone(self.radb.getTask(id=task_id)) + # self.assertEqual(self.radb.getSpecification(spec_id), []) + + + + # ------------ tests below may overlap with Jorrit's tests in RT-TAsk10811 + + def test_insertResourceClaim_when_radb_empty_succeeds(self): + spec_and_task_dict = self.radb.insertSpecificationAndTask(mom_id=0, otdb_id=0, task_status="prescheduled", + task_type="observation", starttime='2017-05-10 10:00:00', + endtime='2017-05-10 12:00:00', content="", cluster="CEP4") + + claim_id = self.radb.insertResourceClaim(resource_id=0, task_id=spec_and_task_dict.get('task_id'), + starttime='2017-05-10 10:00:00', + endtime='2017-05-10 12:00:00', + status="claimed", # <-- change to "tentative" before merging! + session_id=1, claim_size=1, username="", user_id=0) + + self.assertIsNotNone(claim_id) + + def test_insertResourceClaim_when_out_of_storage_fails(self): + spec_and_task_dict = self.radb.insertSpecificationAndTask(mom_id=0, otdb_id=0, task_status="prescheduled", + task_type="observation", starttime='2017-05-10 10:00:00', + endtime='2017-05-10 12:00:00', content="", cluster="CEP4") + abnormally_huge_claim_size = 1000000000000000000000000000000000000000000000000000000000000000000000000000000000 + + claim = {'resource_id': 0, + 'starttime': '2017-05-10 10:00:00', + 'endtime': '2017-05-10 12:00:00', + 'status': 'claimed', # <-- should become tentative before merging! + 'claim_size': abnormally_huge_claim_size, + 'used_rcus': None} + + claim_ids = self.radb.insertResourceClaims(spec_and_task_dict.get('task_id'), [claim], + session_id=1, username="", user_id=0) + + self.assertEqual(claim_ids, []) if __name__ == "__main__": -- GitLab